В 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!'
Итак, как вы можете видеть, использование символа &
в значительной степени избыточно, за исключением случая, когда нет списка аргументов. В этом случае подпрограмма вызывается с текущими значениями в @_
.
Сигиль &
также имеет другое специальное поведение, связанное с прототипами Perl. Скажем, вы писали свою собственную функцию keys
и хотели, чтобы она вела себя как Perl:
sub mykeys (\%) {keys %{$_[0]}}
Здесь прототип (\%)
сообщает Perl, что первый аргумент mykeys
должен быть литеральным хешем (который будет передан как ссылка на хеш).
my $hashref = {...};
say for mykeys %$hashref;
Если по какой-то причине вам нужно было обойти это требование (как правило, не самая лучшая идея), вы могли бы написать это:
say for &mykeys( $hashref ); # note that there is no `%`
В этом случае добавление &
перед подпрограммой отключает проверку прототипа и любые последующие действия, которые он выполнил (например, получение ссылки). В этом случае &
- это в основном утверждение, что вы точно знаете, какие аргументы нужны mykeys
, и не хотите, чтобы perl мешал.
В целом, следует избегать использования &
в подпрограммах, если вы явно не хотите одно из действий, о которых я упоминал выше.
Наконец, &
также необходимо, когда вы ссылаетесь на фактическую ссылку на код:
my $coderef = \&hello;
или
if (defined &hello) {print "hello is defined\n"} # but is not called
Как уже упоминалось, оператор 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
Вы можете использовать ключевое слово 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