印記

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 呼叫,但是對於函式。