印记

Perl 有许多符号:

$scalar = 1; # individual value
@array = ( 1, 2, 3, 4, 5 ); # sequence of values
%hash = ('it', 'ciao', 'en', 'hello', 'fr', 'salut'); # unordered key-value pairs
&function('arguments'); # subroutine
*typeglob; # symbol table entry

这些看起来像 sigils,但不是:

\@array; # \ returns the reference of what's on the right (so, a reference to @array)
$#array; # this is the index of the last element of @array

如果你愿意,可以在 sigil 之后使用牙套。偶尔,这会提高可读性。

say ${value} = 5;

当你使用不同的符号来定义不同类型的变量时,可以根据你使用的符号以不同的方式访问相同的变量。

%hash;            # we use % because we are looking at an entire hash
$hash{it};        # we want a single value, however, that's singular, so we use $
$array[0];        # likewise for an array. notice the change in brackets.
@array[0,3];      # we want multiple values of an array, so we instead use @
@hash{'it','en'}; # similarly for hashes (this gives the values: 'ciao', 'hello')
%hash{'it','fr'}; # we want an hash with just some of the keys, so we use %
                  # (this gives key-value pairs: 'it', 'ciao', 'fr', 'salut')

对于参考文献尤其如此。为了使用引用值,你可以将符号组合在一起。

my @array = 1..5;                    # This is an array
my $reference_to_an_array = \@array; # A reference to an array is a singular value
push @array, 6;                      # push expects an array
push @$reference_to_an_array, 7;     # the @ sigil means what's on the right is an array
                                     # and what's on the right is $reference_to_an_array
                                     # hence: first a @, then a $

这是一个可能不那么容易混淆的思考方式。正如我们之前看到的,你可以使用大括号来包裹 sigil 右侧的内容。因此,你可以将 @{} 视为采用数组引用并为你提供引用数组的内容。

# pop does not like array references
pop $reference_to_an_array; # ERROR in Perl 5.20+
# but if we use @{}, then...
pop @{ $reference_to_an_array }; # this works!

事实证明,@{} 实际上接受了一个表达式:

my $values = undef;
say pop @{ $values };       # ERROR: can't use undef as an array reference
say pop @{ $values // [5] } # undef // [5] gives [5], so this prints 5

……同样的伎俩也适用于其他符号。

# This is not an example of good Perl. It is merely a demonstration of this language feature
my $hashref = undef;
for my $key ( %{ $hashref // {} } ) {
  "This doesn't crash";
}

…但是如果对于印记的论证很简单,你可以把括号留下来。

say $$scalar_reference;
say pop @$array_reference;
for keys (%$hash_reference) { ... };

事情可能变得过于奢侈。这是有效的,但请 Perl 负责任地。

my %hash = (it => 'ciao', en => 'hi', fr => 'salut');
my $reference = \%hash;
my $reference_to_a_reference = \$reference;

my $italian = $hash{it};                              # Direct access 
my @greets = @$reference{'it', 'en'};                 # Dereference, then access as array
my %subhash = %$$reference_to_a_reference{'en', 'fr'} # Dereference ×2 then access as hash

对于大多数正常使用,你只需使用没有印记的子程序名称。 (没有 sigil 的变量通常被称为 barewords。)& sigil 仅在有限数量的情况下有用。

  • 引用子例程:

    sub many_bars { 'bar' x $_[0] }
    my $reference = \&many_bars;
    say $reference->(3); # barbarbar
    
  • 调用函数忽略其原型。

  • 结合 goto,作为一个稍微奇怪的函数调用,将当前调用框架替换为调用者。想想 linux exec() API 调用,但是对于函数。