![]() |
![]() |
|
||
![]() |
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [1 апреля 2002 г.] |
В предыдущей набле я говорил о том, как удобно использовать массивы и хэши в языке PHP, а также о том, что вот сейчас начнется недетский разговор о Perl. Если вы плохо ориентируетесь в терминах и еще не прочитали эту наблу, вернитесь к ней (даже если и не собираетесь использовать PHP). Сравнение всегда было одним из самых действенных принципов вникания.
Неужели все так плохо?.. Не |
В этой набле разговор пойдет о свойствах основных типов переменных Perl. В следующей набле будет рассмотрен гораздо более сложный материал, касающийся ссылок и многомерных структур данных. Но не все сразу.
Сейчас я попытаюсь объяснить все так, чтобы это показалось простым. Шаг к
Итак, скалярная переменная Perl может хранить одно из трех значений: строку, вещественное число или же ссылку на произвольный объект. Точка. В отличие от PHP, в котором по имени переменной нельзя узнать, какого она типа (
Вернее будет сказать несколько иначе: любой скалярный объект, который может стоять в левой части оператора присваивания, всегда начинается со знака
К сожалению, из этого правила существуют |
Вот несколько примеров скаляров:
print $n; # число или строка print $#A; # номер последнего элемента в массиве @A print $A[1]; # элемент массива с индексом 1 print $$r; # разыменование ссылки на скаляр
Забегая вперед, скажу, что даже обращение к скалярному элементу массива происходит при помощи вездесущего доллара. А вы
В Perl, вообще говоря, существует всего 4 вида объектов: это скаляры, массивы, хэши и списки (есть еще тип-глобы, TYPEGLOBS, однако сейчас нам до них нет дела). Причем понятие список особое. Чтобы лучше его понять, представьте себе число 10 в тексте программы и число
Список задает в программе некоторую последовательность скаляров, массив |
Список в программе на Perl задается в круглых скобках любого уровня вложенности:
(1,2,3) (((1,2,3))) ((1),(2),(3))
Таким образом, все три приведенные выше строчки задают один и тот же список, содержащий числа 1, 2 и 3. Вложенность скобок не играет никакой
Что же можно сделать с таким списком?.. То же самое, что вы делаете с обычными числами в программе: вы присваиваете их чему-то, какой-то переменной (что с ними еще
Как ни странно, но один и тот же список в программе может в итоге принять весьма причудливую форму в зависимости от того, какой переменной его присвоили.
|
Мы знаем, что в Perl переменные разных типов обозначаются по-разному (скаляры, например, всегда начинаются с доллара, а
$a = (10,20,30);
Оказывается, в этом случае в переменной окажется значение последнего элемента списка, то есть 30. Первые два элемента безвозвратно потерялись, это и понятно: нельзя все величины сохранить в малюсеньком скаляре.
Все это очень смахивает на поведение «оператора запятая», который имеется в Си. В Perl также существует этот оператор, однако вот в таком, списковом, так сказать, ракурсе.
|
Имеет место более общее утверждение. Как известно, присвоить можно только
Этот момент иногда оказывается весьма существенным. Например, функции могут возвращать либо скаляр, либо список, и ничто иное. Они не могут вернуть ни массив, ни хэш.
|
Раз существует всего два типа «обменных» данных, должны существовать и какие-то правила перевода одного типа в другой. Эти правила довольно просты. Когда список нужно перевести в скаляр, просто берется его последний элемент, остальные откидываются. Когда скаляр нужно перевести в список, Perl «мысленно» обрамляет его скобками. Что может быть проще?..
Вернувшись к нашим баранам, можно легко догадаться, что будет, если присвоить список переменной типа массив (такие переменные всегда предваряются знаком
@A = (10,20,30);
Конечно, Ларри
О массивах. Perl был создан значительно раньше, чем PHP, а потому, увы, массивы в нем могут содержать только скаляры. В ранних версиях языка (четвертой и ниже) это было настоящим бичом
Итак, если Perl видит слева нечто, начинающееся с
Вот несколько примеров:
# присваиваем значение всему массиву @A = (10,20); # присваиваем один массив другому @B = @A; # то же самое - все равно в первом случае # массив разворачивается в список... @B = ((@A))
Я уже говорил о том, как преобразуются между собой скалярные и списковые величины. Настало время посмотреть, как массивы преобразуются в список и в скаляр. Ну со списком все
# помещаем в $a число элементов @A $a = @A; # помещаем в @B все, что было в @A, # и еще парочку элементов @B = (1, @A, 2);
В первом случае массив
Ну вот, наконец-то удалось описать понятие скалярного и спискового контекстов. Далее я буду пользоваться только ими, избегая фраз типа «преобразование массива в скаляр».
|
Для явного указания того, что выражение нужно трактовать в скалярном контексте, даже существует специальный оператор
# вывести число элементов хэша @K = keys %data; print scalar(@K);
Функция
# вывести число элементов хэша print scalar(keys %data);
Хотя о хэшах мы еще не говорили, нетрудно понять, что делает данный код: вначале он при помощи функции
На самом деле, все в порядке, и программа работает как надо. Все дело в том, что в данном примере функция
По-правде говоря, этот флажок передается даже и без слова |
Итак, функция
sub keys
{ ... работаем ...
return wantarray? @K : scalar(@K);
}
Скалярный контекст для получения числа элементов массива (но не списка!) удобно применять, например, в цикле
for(my $i=0; $i<@A; $i++) {...}
Это выглядит несколько лучше, чем такой код:
for(my $i=0; $i<=$#A; $i++) {...}
На всякий случай я приведу еще пару примеров работы с массивами.
# получаем элемент массива $a = $A[$i*2-1]; # последний элемент - вот так просто $b = $A[-1]; # предпоследний и последний элементы ($a, $b) = ($A[-2], $A[-1]);
В последнем примере мы видим, что
# перебор массива
foreach my $elt (@A) {...}
# или по-другому
for(my $i=0; $i<@A; $i++) {...}
# добавление элемента в конец массива
push @A, 10;
# добавление трех элементов (можно без скобок)
push @A, (10, 20, 30)
# добавление массива @B в начало @A
unshift @A, @B;
В отличие от PHP, хэши
Никогда не путайте массивы и
%H = (
'a', 'aaa', # первая пара "ключ-значение"
'b', 'bbb', # вторая пара
'c', 'ccc', # третья
);
Как было написано в предыдущей набле, запятая в конце последней пары допускается, это не ошибка. |
Обилие апострофов несколько раздражает, а потому в Perl был придуман новый знак
%H = (
a => 'aaa', # первая пара "ключ-значение"
b => 'bbb', # вторая пара
c => 'ccc', # третья
);
Во всем остальном этот значок полностью аналогичен запятой, поэтому не смущайтесь, когда увидите такой вызов функции:
print 10=>" "=>20=>" "=>30;
Присвоить хэшу скаляр, конечно же, |
Когда хэш трактуется в списковом контексте, он превращается в 2*N значений, где
Нельзя сказать, что в PHP хэши удобнее. Здесь просто другая идеология. Везде, где требуется предсказуемый порядок элементов, используйте массивы, а где поиск по |
Так как значениями (и ключами) в хэше может быть только скаляр, для доступа по ключу опять же используется всеми любимый доллар, однако скобки на этот раз не квадратные, а фигурные:
# присваиваем значение хэшу целиком
%H = (a=>'aaa', b=>'bbb');
# получаем доступ по ключу...
my $a = $H{'a'};
# а можно и так
$H{b} = 100;
Заметьте, что Perl настолько услужлив, что позволяет пропускать кавычки и апострофы внутри фигурных скобок. Красота, да и только. |
Наконец, когда хэш трактуется в скалярном контексте, он возвращает довольно интересную строку, которая выглядит вот так:
Когда место заканчивается, Perl автоматически выделяет для хэша новый участок памяти, уже побольше размером, копируя туда ключи, и тратится на это довольно значительное количество ресурсов. О принципах хэширования написано много литературы, и я, пожалуй, отошлю вас к ней, если у вас возникли какие-то вопросы о памяти.
|
Ну и несколько примеров работы с хэшами.
# создаем хэш из списка
%H = (a=>10, b=>20, c=>30);
# перебираем все элементы
while(my ($k,$v)=each(%H)) {...}
# перебираем ключи в алфавитном порядке
foreach my $k (sort keys %H) {...}
# добавляем элемент в хэш
$H{d} = 40;
# удаляем элемент из хэша
delete $H{a};
# проверяем существование ключа
if(exists $H{b}) {...}
В качестве резюме к этой набле приведу небольшую табличку преобразований различных объектов. В левой части таблицы указан преобразуемый объект, а в
| Что преобразуем | Тип | В скаляр | В список |
| скаляр | значение | (значение) | |
| список | последний элемент | (3,4,5) | |
| массив | число элементов | (элементы) | |
| хэш | M/N | (k1,v1, k2,v2, ...) |
В следующей набле мы поговорим о более сложных, но в то же время и более мощных аспектах работы с массивами, хэшами и ссылками Perl. Я расскажу, как можно создавать многомерные структуры данных (массивы хэшей, хэши массивов и т. д.), а также о том, как же запомнить этот «проклятущий синтаксис» и начать применять его свободно.
![]() |
| ||||||||||||||||||||||||||||
| Дмитрий Котеров | 1 апреля 2002 г. ©1999-2010 | | Контакт | Вернуться к оглавлению |