среда, 17 сентября 2008 г.

Игры со ссылками в Perl: многомерный массив


Массивы Perl (в смысле хэши и списки) не могут быть многомерными, но с помощью механизма ссылок их легко можно эмулировать - т.е. создать, например, хэш, содержащий ссылки на другие хэши. Ниже приводится вполне извращенная демонстрация этой возможности. Если кому-то хочется больших извращений, читайте man-страницу perlref(1).


#!/usr/bin/perl -w

# программа создает хэш, содержащий ссылки на список,
# который в свою очередь содержит ссылки на хэш,
# элементы хэша - ссылки на дескрипторы ввода-вывода


# для начала откроем парочку дескрипторов
open FD, '>/tmp/myout';
open PD, '|nroff -man';

# записываем значения в наш хэш:
# полный синтаксис такой

$a{kiwi}->[7]->{deer} = *FD;
# но работает и в сокращенном виде
$a{'.TH'}[1]{elk} = *PD;
# синтаксис *foo - это ссылка на все,
# что угодно (global reference),
# работает и для дескрипторов ввода-вывода

$a{banana}[5]{wapiti} = *STDOUT;

# а теперь посмотрим, что в нашем хэше
foreach $k (sort keys %a) {
# элемент хеша $a{$k} - ссылка на список,
# значит, $#{$a{$k}} - число элементов в нем

for ($m = 0; $m <= $#{$a{$k}}; $m++) {
# проверка на defined понадобилась
# т.к. добавление второго элемента в список
# автоматически добавляет нулевой, первый и т.д.

if (defined $a{$k}[$m]) {
foreach $n (sort keys %{$a{$k}[$m]}) {
# печатаем в наш дескриптор
# почему-то использование $a{$k}[$m]{$n}
# в print дает syntax error,
# поэтому забиваем костыль

$fh = $a{$k}[$m]{$n};
print $fh join(' ', $k, $n, $m), "\n";
# и не забудем его закрыть
if (fileno($fh) != 1) {
# не stdout
close $fh;
}
}
}
}

Итак, в результате работы нашей програмы на стандарном выводе должна появиться строка:
banana wapiti 5
в файле /tmp/myout - строка:
kiwi deer 7
а на вводе команды nrof -man (а потом - в отформатированном виде - тоже на стандартном выводе) директива:
.TH elk 1

P.S. если хочется узнать, ссылкой на какой тип данных является переменная $x, поможет функция ref($x) - возвращает ARRAY, HASH и т. д.

1 комментарий:

Анонимный комментирует...
Этот комментарий был удален администратором блога.