Perl语法sigil

时间:2011-02-17 10:00:01

标签: perl syntax

我知道在没有它的情况下在潜艇前使用&是什么,潜艇仍然可以运行。

而且,perl变量前面的my

我知道它是针对严格的语言语法,或者是什么不是,但为什么不将它们作为一个标准,每个变量都需要由my声明?

修改

感谢您的所有讨论/答案,我希望接受您的许多答案,但由于我只能接受一个答案,我会接受其他用户可能轻松理解的答案。

5 个答案:

答案 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变量面前。

设置块范围

  

我知道它是针对严格的语言语法或者不是,但是为什么不将它们作为一个标准,每个变量都需要由我声明?

  1. 向后兼容性(因此use strict;禁止裸变量声明)
  2. 也可以使用ourlocal
  3. 声明变量

答案 3 :(得分:4)

如果您想知道如何编写现代Perl,我建议您阅读Modern Perl吗? 您可以免费购买死树版或下载电子版。

答案 4 :(得分:0)

&仍然有很好的区别:用它来调用(&YourSub)使得当前@_对被调用的子也可见。无论如何,我在我的脚本中使用它主要是出于清晰的原因:它清楚地说明了哪些是我自己的功能,哪些功能来自核心或模块。

关于my。每个教程和文档建议使用use strict;编译指示,因此您也可以使用my声明您的变量。因此,从我的角度来看,情况是相当倒退的:如果范围对于最佳实践非常重要,那么默认情况下变量的范围是正常的(就像我们现在用my说的那样)并且当我们确实需要全局时变量,我们应该将它们声明为那样。我知道这是perl的遗产,但仍然违背了Perl的意识形态,以避免冗余。每次使用my进行声明都可以被某种编译指示所覆盖。 [抱歉,robobooga,可能离你的问题太远了]