VP>> my %hash2 = qw(d 3 e 4);
VP>> $hash1{'c'} = %hash2;
AM> А %hash2 можно динамически создавать по мере появления новых ключей у
AM> %hash1?
не всегда :) есть perldsc, вот его кратокое изложение
=== Cut ===
ну очень краткое :) итак, как работать в perl с вложенными массивами и хешами
до perl5 в перле было всего три (основных) типа данных и имя переменной
полностью определяло, данные какого типа она хранит
$x - хранит ЗHАЧЕHИЕ (число или строку)
@x - хранит список ЗHАЧЕHИЙ
%x - хранит список пар строка->ЗHАЧЕHИЕ
в perl5 всё осталось также, только понятие ЗHАЧЕHИЯ было расширено - теперь это
может быть ССЫЛКА на массив или хеш. очень важная тонкость - в отличие от
самого массива или хеша, ССЫЛКА на них является скаляром. вот смотрите:
@a = (1,2);
$a = [ (1,2) ]; # квадратные скобки превращают массив/хеш в ССЫЛКУ на массив
%b = (1=>2);
$b = { (1=>2) }; # фигурные скобки превращают массив/хеш в ССЫЛКУ на хеш
обратите внимания - круглые скобки используются только для группировки, а
квадратные и фигурные являются ОПЕРАТОРОМ, превращающим СОСТАВHОЕ ЗHАЧЕHИЕ в
ССЫЛКУ. Внутри []/{} круглые скобки обычно опускают, я привёл их лишь для
удобства понимания единственной существенной разницы между этими действиями
если же вы и внешние круглые скобки замените на []/{}, то опять получите
скаляр, и его надо будет присваивать тоже скаляру:
$e = [ [1,2], [3,4] ]; # ССЫЛКА на массив, состоящий из ССЫЛОК на массивы
поскольку перловые функции обычно ожидают "развёрнутый" массив/хеш,
пользоваться таким скаляром будет неудобно. да и к элементам его доступ
неочевиден - $e->[0][1]. собственно, "->" - оператор разыменования ССЫЛОК, и
для доступа к элементам @c он тоже используется, но перл вставляет его неявно:
$c[0][1] эквивалентно $c[0]->[1]. То есть, $c[0] возвращает нам ССЫЛКУ на
массив, стрелка её разыменовывает (превращает ССЫЛКУ в массив) и затем второе
индексирование "[1]" возвращает нам элемент этого массива
наверно, уже понятно, что $e->[0][1] на самом деле работает как $e->[0]->[1]:
разыменовываем, берём элемент, снова разыменовываем, и снова берём элемент. с
массивами хешей, и со сколь угодно более сложными структурами данных всё точно
также. разумеется, их можно произвольно смешивать:
вот, в общем-то, и всё. добавлю несколько дополнительных замечаний
операторы []/{} создают КОПИИ переданных им ЗHАЧЕHИЙ. если вы хотите вместо
этого получить ССЫЛКУ на ТЕ ЖЕ данные, используйте оператор "". кстати, эти
операторы можно комбинировать:
@a = (1,2);
@b = (3,4);
@c = ( [@a], [@b] ); # @c содержит (ССЫЛКИ на) копии массивов a и b
@d = ( @a, @b ); # @d содержит ССЫЛКИ на массивы a и b
@e = ( [@a, @b], [[@a], [@b]] );
@e - трёхмерный массив,
$e[0][0][$i] эквивалентно $a[$i]
$e[0][1][$i] эквивалентно $b[$i]
$e[1][0][$i] содержат копии $a[$i]
$e[1][1][$i] содержат копии $b[$i]
т.е. теперь присваивания $a[$i] изменят также ЗHАЧЕHИЯ $d[0][$i] и $e[0][0][$i]
и наоборот. ссылки полезны при передаче сложных структур данных в функции (чтоб
перл не разворачивал всё в один бессмысленный список) и при манипуляциях со
связными структурами данных, типа деревьев и связных списков
не используйте операцию получения ссылки без необходимости, поскольку перл
возвращает ССЫЛКУ не на данные как таковые, а на переменную, и в дальнейшем что
бы ни присвоили этой переменной - вы увидите это по своей ссылке:
@a = (1,2);
$ref = @a;
@a = (3,4);
# теперь $ref указывает на новое содержимое @a
второе замечание - многие встроенные операторы перла рассчитаны на то, что им
на вход подадут переменную-массив или хеш. но никак не ССЫЛКУ. для того, чтобы
превратить одно в другое, используются конструкции @{...} и %{...}:
push @{$c[0]}, 0; # $c[0] - ССЫЛКА на массив, @{$c[0]} - сам массив
остатнее читайте в perldsc. там же есть готовые куски кода для всех возможных
манипуляций с массивами массивов, массивами хешей, хешами массивов и хешами
хешей. от себя посоветую использовать модуль Data::Dumper для изучения
результатов своего творчества :)
use Data::Dumper; # for exporting values from Perl to Ruby
#$Data::Dumper::Indent = 0; # one-line output
#$Data::Dumper::Terse = 1; # print no assignments to $VARn
#$Data::Dumper::Useqq = 1; # quote unprintable chars
#$Data::Dumper::Deepcopy = 1; # ??? are we really need this? ;)