Многое в языке Perl кажется новичку странным, неожиданным, необъяснимым. При внимательном рассмотрении так оно и оказывается. Попробуем произвести весьма простую операцию: распечатаем массив. Получим:
1 my @words = qw(awesome cats hunter); 2 print @words; # -> "awesomecatshunter" 3 print "@words"; # -> "awesome cats hunter" 4 print "" . "@words"; # -> "awesome cats hunter" 5 print "" . @words; # -> 3
Отчего же так происходит? На первый взгляд вывод должен быть одинаковым, как независимо от наличия кавычек произошло бы со скалярами:
1 $word = "supersonic"; 2 print $word; 3 print "$word"; 4 print "" . "$word"; 5 print "" . $word; # -> все будет "supersonic" без перевода каретки
Как обычно для Perl, вступают в действие темные силы контекстов. В первом варианте мы имеет дело со списочным контекстом. Т.е. просто передаем список аргументов функции print и она их печатает, разделяя строкой, содержащейся в магической переменной $, . Кроме того, переменная $\ печатается в конце списка. По умолчанию обе эти переменные не определены, что равносильно значению "" в строковом контексте. Так что print не только не переводит каретку, но и лепит содержащиеся в списке строки вплотную без пробелов. Впрочем, оба этих поведения лишь непривычны, например, питонисту, но весьма правильны и удобны для обрабоки текста. Попробуем теперь поменять значения магических переменных:
1 $, = "--"; 2 $\ = "END\n"; 3 print @words; # -> "awesome--cats--hunterEND" с возвратом каретки
Пойдем дальше. Если мы помещаем идентификатор массива в строку с двойными кавычками (см. 3я и 4я строки первого листинга заметки), вступает в дело контекст строковой интерполяции. В этом контексте массив интерполируется в строку с разделителем $" по умолчанию равному " " (пробел). Эту фичу можно красиво использовать для отладочного отображения аргументов функции. Аргументы могут содержать пробелы, и для ясности сепаратор можно локально поменять:
1 sub is_fatherof { 2 if ($debug) { 3 local $" = "]["; 4 print "args = [@_]\n"; 5 } 6 conquer_the_universe...; 7 } 8 9 $debug = 1; 10 is_fatherof('Darth Vader', 'Luke Skywalker'); # -> "args = [Darth Vader][Luke Skywalker]"
Вобщем, строковая интерполяция массива эквивалентна join $", @words
Последний пример (print "" . @words) демонстрирует поведение массива в скалярном контексте. Да, в этом контексте массив заменяется своей длиной. Perl is SATAAAN!!! Спасибо за внимание.