我知道在没有它的情况下在潜艇前使用&
是什么,潜艇仍然可以运行。
而且,perl变量前面的my
。
我知道它是针对严格的语言语法,或者是什么不是,但为什么不将它们作为一个标准,每个变量都需要由my
声明?
修改
感谢您的所有讨论/答案,我希望接受您的许多答案,但由于我只能接受一个答案,我会接受其他用户可能轻松理解的答案。
答案 0 :(得分:12)
在Perl中,函数调用已经过优化,不需要&
符号。声明子例程时:
sub hello {print "world\n"}
您可以将其称为hello;
或hello();
或&hello();
,这些都会做同样的事情。
如果你的子程序有参数,那就有点不同了:
sub hello {print "Hello, @_!\n"}
hello 'World'; # prints 'Hello, World!'
hello('World'); # same
&hello('World'); # same
hello; # prints 'Hello, !'
&hello(); # same
&hello; # different, uses whatever was in @_ when hello was called
@_ = 'Bob';
hello; # prints 'Hello, !'
&hello(); # prints 'Hello, !'
&hello; # prints 'Hello, Bob!'
正如您所看到的,使用&
sigil在很大程度上是多余的,除非没有参数列表。在这种情况下,使用@_
中的当前值调用子例程。
&
sigil还有另一个与Perl原型相关的特殊行为。假设您正在编写自己的keys
函数,并希望它的行为类似于Perl:
sub mykeys (\%) {keys %{$_[0]}}
这里(\%)
原型告诉perl mykeys
的第一个参数必须是文字哈希(它将作为哈希引用传入)。
my $hashref = {...};
say for mykeys %$hashref;
如果由于某种原因你需要绕过这个要求(通常不是最好的想法),你可以这样写:
say for &mykeys( $hashref ); # note that there is no `%`
在这种情况下,在sub之前添加&
会禁用原型检查以及它将执行的任何后续操作(如获取引用)。在这种用法中,&
基本上是一个断言,你确切地知道mykeys
需要什么参数,并且你不希望perl妨碍它。
通常,应避免在子例程上使用&
,除非您明确要求我在上面提到的行为之一。
最后,当您引用实际的代码引用时,还需要&
:
my $coderef = \&hello;
或
if (defined &hello) {print "hello is defined\n"} # but is not called
正如其他人所提到的,my
运算符在当前词法范围内声明变量。加载use strict;
pragma时需要它。 Perl有两种类型的变量,用my
声明的词法变量和包变量。
my
变量存在于所谓的词法填充中,这是每次引入新作用域时由Perl创建的存储空间。包变量存在于全局符号表中。
use strict;
use warnings;
$main::foo = 5; # package variable
{ # scope start
my $foo = 6;
print "$foo, $main::foo\n"; # prints '6, 5';
} # scope end
print "$foo, $main::foo\n"; # syntax error, variable $foo is not declared
您可以使用our
关键字为全局变量创建词法别名:
use strict;
our $foo = 5; # $main::foo == $foo
{ # scope start
my $foo = 6;
print "$foo, $main::foo\n"; # prints '6, 5';
} # scope end
print "$foo, $main::foo\n"; # prints '5, 5'
# since $foo and $main::foo are the same
答案 1 :(得分:8)
my
将变量限制为当前范围。使用您应该使用的use strict
编译指示,必须声明变量(例如使用my
)。由于非常短的脚本的灵活性原因,存在替代方案。
由于Perl默认将-sigil-less字解释为子例程,因此很少使用&
,但如果要创建对子例程的引用,则很有用。
sub say_hi { print "hi\n" }
my $sub_ref = \&say_hi;
答案 2 :(得分:5)
我可以知道&和在没有它的情况下,在潜艇前面,潜艇仍能够行驶。
向后兼容Perl 4
而且,我在perl变量面前。
设置块范围
我知道它是针对严格的语言语法或者不是,但是为什么不将它们作为一个标准,每个变量都需要由我声明?
use strict;
禁止裸变量声明)our
或local
答案 3 :(得分:4)
如果您想知道如何编写现代Perl,我建议您阅读Modern Perl吗? 您可以免费购买死树版或下载电子版。
答案 4 :(得分:0)
&
仍然有很好的区别:用它来调用(&YourSub
)使得当前@_
对被调用的子也可见。无论如何,我在我的脚本中使用它主要是出于清晰的原因:它清楚地说明了哪些是我自己的功能,哪些功能来自核心或模块。
关于my
。每个教程和文档建议使用use strict;
编译指示,因此您也可以使用my
声明您的变量。因此,从我的角度来看,情况是相当倒退的:如果范围对于最佳实践非常重要,那么默认情况下变量的范围是正常的(就像我们现在用my
说的那样)并且当我们确实需要全局时变量,我们应该将它们声明为那样。我知道这是perl的遗产,但仍然违背了Perl的意识形态,以避免冗余。每次使用my
进行声明都可以被某种编译指示所覆盖。 [抱歉,robobooga,可能离你的问题太远了]