编写严格编译代码的最佳方法
检查提供给子例程的参数以进行严格编译的最佳方法是什么(我的解决方案有效,但有更好的方法?)
我有一个大型旧库,我想更正代码,以便我可以添加 use strict;对此,我的大多数错误都是这样的(在页面加载时会生成 189 个错误):
Use of uninitialized value in string eq at ../lib/cgilibtest.pl line 1510
Use of uninitialized value in concatenation (.) or string at ../lib/cgilibtest.pl line 1511.
它们是由这样编写的子例程生成的:
#!/usr/bin/perl -w
sub example()
{
my $var1 = shift @_;
my $var2 = shift @_;
my $var3 = shift @_;
if($var2 eq ""){var2 = "something";} # this line generates the first type of error beacause $var2 is not defined
return "var1 = ".$var1.", var2 = ".$var2.", var3 = ".$var3; # this line generates the second type of error, beacause $var3 is not defined
}
print "Content-type: text/html\n\n";
$someVar = &example("firstVar");
print $someVar;
我的解决方案是使用三元运算符并将它们写为:
#!/usr/bin/perl -w
use strict;
sub example()
{
my $var1 = ($_[0])?$_[0]:"";
my $var2 = ($_[1])?$_[1]:"something";
my $var3 = ($_[2])?$_[2]:"";
return "var1 = ".$var1.", var2 = ".$var2.", var3 = ".$var3;
}
print "Content-type: text/html\n\n";
my $someVar = &example("firstVar");
print $someVar;
在 PHP 中我使用 函数示例 ($var1, $var2 = null, $var3 = null){...}
PS 如果有人知道关于“在 Perl 中编写严格代码”的好教程或手册,请留下一个链接。
谢谢。
What is the best way to check arguments provided to subroutines to compile with strict ( my solution works but there is a better way of doing it ? )
I have a large old library, I want to correct the code so I can add use strict; to it, most of my error are like this (on a page load it generates 189 errors):
Use of uninitialized value in string eq at ../lib/cgilibtest.pl line 1510
Use of uninitialized value in concatenation (.) or string at ../lib/cgilibtest.pl line 1511.
They are generated by subroutines writen like this:
#!/usr/bin/perl -w
sub example()
{
my $var1 = shift @_;
my $var2 = shift @_;
my $var3 = shift @_;
if($var2 eq ""){var2 = "something";} # this line generates the first type of error beacause $var2 is not defined
return "var1 = ".$var1.", var2 = ".$var2.", var3 = ".$var3; # this line generates the second type of error, beacause $var3 is not defined
}
print "Content-type: text/html\n\n";
$someVar = &example("firstVar");
print $someVar;
My solution was to use the ternary operator and write them as:
#!/usr/bin/perl -w
use strict;
sub example()
{
my $var1 = ($_[0])?$_[0]:"";
my $var2 = ($_[1])?$_[1]:"something";
my $var3 = ($_[2])?$_[2]:"";
return "var1 = ".$var1.", var2 = ".$var2.", var3 = ".$var3;
}
print "Content-type: text/html\n\n";
my $someVar = &example("firstVar");
print $someVar;
in PHP I use function example ($var1, $var2 = null, $var3 = null){...}
P.S. If someone knows a good tutorial or manual about "write strict code in perl" please leave a link to it.
Thank you.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如果你按照它所说的去做,你将至少编写符合
严格
和警告
的代码。我看到的是 uninit 警告。而且,uninit 警告带有
警告
,而不是严格
。尽管它通常与严格齐头并进。对于您的特定错误,重要的是要认识到,当您移动 arg 数组(我倾向于将其称为“甲板”)时,方法/函数的用户可能没有在该位置传递任何内容。因此,这是一个很好的习语;
''
尚未初始化,因此不会收到警告。三元数也是一种很好的方法,我在生产代码中充分使用了它们。当然,还有另一个问题。如果你看一下上面的代码,我在期待什么?我预计
$var1
可能尚未传递任何数据。如果是这种情况,并且我仍然想将其字符串化 - 并且本地代码中有足够这样的情况 - 有时你只需这样做:它相当于用一堆代码来执行此操作变量:
这个想法并不是对未初始化的数据感到惊讶——拥有适合实例的策略,而不是盲目地按照标准进行编码。
由于您的子程序足够简单,因此上面的代码将起作用。但您可能希望让它在未来做更多的事情,所以我建议使用以下构造来隔离我们可以接受未初始化值的部分以及您不想被抓住的部分。
do
块对此也很有用。当然,作为变量传递的任何内容,您也可以使用
map
进行过滤。如果您只想处理 undef,则以下方法有效。undef
。现在,很多时候人们检查未定义的变量只是为了发牢骚。由于 Perl 的消息已经变得更好,也许它们将来可以改进。可能没有必要专门发出嘎嘎声。
然而,如果没有显式的
or die
,如果$feldman
未定义,上面的代码肯定会死掉。您无法对未定义的值调用方法,因此存在不专门检查的情况。如果 $feldman 未定义,那么您没有创建它,您只需从未定义到错误消息进行多一层推断。两者都没有告诉我们为什么该对象没有被创建,只是它没有被创建。 (构造函数至少应该对它没有的东西吹毛求疵。)you follow what it says, you will at least be writing code compliant with
strict
andwarnings
.What I see is uninit warnings. And, uninit warnings come with
warnings
, notstrict
. Though it usually goes hand in hand with strict.For your particular error, it's important to realize that when you shift the arg array (which I have a tendency to call "deck") that the user of the method/function might not have passed anything in that position. Thus this is a good idiom;
''
is not uninitialized, and so won't get the warning. Ternaries are also a good means and I use them enough in my production code.Of course, there's another issue though. If you take a look at the code above, what am I expecting? I'm expecting that
$var1
might not have been passed any data. If that is the case, and I still want to stringify it--and there are enough cases like this in the local code--sometimes you just do this:It's equivalent code to doing this with a bunch of variables:
The idea is not to be taken by surprise with uninitialized data--having a policy that fits the instance, rather than slavishly coding to a standard.
Since your sub is easy enough, the above code will work. But you probably want to make it do more in the future, so I suggest the following construct to isolate the parts that we're okay with uninitialized values and where you don't want to be caught unaware.
do
blocks are also useful for this.Of course anything that you pass as a variable, you can also filter with a
map
. The following works if you just want to take care of undefs.undef
of not.Now, a lot of times people check for undefined variables just to croak. Since Perl's messages have gotten better, and perhaps if they could improve in the future. It might not be necessary to croak specifically.
However without the explicit
or die
, the code above will definitely die if$feldman
is undefined. You can't call a method on an undefined value, so there is case for not specifically checking. If$feldman
is undefined, then you didn't create it, there is just one more level of inference you have to make from undefined to the error message. Neither tells us why the object was not created, just that it wasn't. (The constructor should at least have carped about something it didn't have.)我赞同查看Perl 最佳实践的建议。达米安康威是一位伟大的老师。还要记住,这本书并不是教条式地阅读,即使你不采纳的建议也值得考虑。
对于全部采用相同默认值的位置参数,我经常这样做:
然而,更灵活的是编写使用命名参数的函数。这种方法有几个好处,其中之一是可以轻松处理默认值:
如果我没记错的话,PBP 讨论了这种合并哈希的技巧,这在许多情况下都很有用。
I would second the recommendation to look at Perl Best Practices. Damian Conway is a great teacher. Also bear in mind that the book is not intended to be read dogmatically, and even suggestions that you don't adopt are worth thinking over.
For positional arguments that all take the same default value, I often do something like this:
Even more flexible, however, is to write functions that use named arguments instead. This approach has several benefits, one of them being the ease with which default values can be handled:
If I recall correctly, PBP discusses this trick of merging hashes, which is useful in many contexts.