Perl语法sigil

rob*_*oga 8 syntax perl

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

而且,my在perl变量前面.

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

编辑

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

Eri*_*rom 12

在Perl中,函数调用已经过优化,不需要&始终使用sigil.声明子例程时:

sub hello {print "world\n"}
Run Code Online (Sandbox Code Playgroud)

你可以把它作为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!'
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,&除了没有参数列表的情况外,使用sigil在很大程度上是多余的.在这种情况下,使用当前值调用子例程@_.

&印记还有另一种与Perl原型相关的特殊行为.假设您正在编写自己的keys函数,并希望它的行为类似于Perl:

sub mykeys (\%) {keys %{$_[0]}}
Run Code Online (Sandbox Code Playgroud)

这里的(\%)原型告诉perl第一个参数mykeys必须是一个文字哈希(它将作为哈希引用传入).

my $hashref = {...};

say for mykeys %$hashref;
Run Code Online (Sandbox Code Playgroud)

如果由于某种原因你需要绕过这个要求(通常不是最好的想法),你可以这样写:

say for &mykeys( $hashref );  # note that there is no `%`
Run Code Online (Sandbox Code Playgroud)

在这种情况下,&在sub之前添加禁用原型检查以及它将执行的任何后续操作(如获取引用).在这种用法中,&基本上是一个断言,你确切知道什么参数mykeys需要,并且你不希望perl妨碍.

通常,&应该避免使用on子例程,除非您明确地想要我上面提到的行为之一.

最后,&在您引用实际代码引用时也需要:

my $coderef = \&hello;
Run Code Online (Sandbox Code Playgroud)

要么

if (defined &hello) {print "hello is defined\n"}  # but is not called
Run Code Online (Sandbox Code Playgroud)

正如其他人所提到的,my运算符在当前词法范围内声明变量.use strict;加载编译指示时需要它.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
Run Code Online (Sandbox Code Playgroud)

您可以使用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
Run Code Online (Sandbox Code Playgroud)


Tim*_*Tim 8

my变量限制为当前范围.使用use strict您应该使用的pragma,您必须声明变量(例如with my).由于非常短的脚本的灵活性原因,存在替代方案.

&因为Perl默认解释印记,少言的子程序很少再使用,但如果你想创建到子过程的引用是非常有用的.

sub say_hi { print "hi\n" }
my $sub_ref = \&say_hi;
Run Code Online (Sandbox Code Playgroud)


Que*_*tin 5

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

向后兼容Perl 4

而且,我在perl变量面前.

它设置了块范围

我知道它是用于严格的语言语法或者不是,但是为什么它们只是使它成为一个标准,每个变量都需要由我声明?

  1. 向后兼容性(因此use strict;不允许使用裸变量声明)
  2. 变量也可以用our或声明local

  • 使用`perl -e`而不是'my`编写1个衬垫也更容易. (2认同)