Как мне почтить этот массив Perl-массивов? - PullRequest
4 голосов
/ 27 мая 2010

Рассмотрим этот код Perl

my @a=[[1]];

print $a[0][0];


**output**
ARRAY(0x229e8)

Почему печатается ARRAY вместо 1? Я ожидал, что @a создаст массив размером 1 со ссылкой на второй массив, содержащий только один элемент, 1.

Ответы [ 4 ]

14 голосов
/ 27 мая 2010

Этот материал хитрый. Вы назначили @a как список, содержащий ссылку на массив, который содержит ссылку на массив, что на один дополнительный уровень косвенности больше, чем вы ожидали.

Чтобы получить ожидаемые результаты, вы должны были сказать

@a = ( [ 1 ] );
11 голосов
/ 27 мая 2010

Требуемое значение: $a[0][0][0]. Вы назначаете массив reference в качестве первого элемента массива @a.

Это похожая вещь:

my @a = 'scalar';

И это создаст массив из 1 слота со строкой 'scalar' в качестве единственного элемента. Поэтому, когда вы присваиваете скаляр для массива, Perl пытается сделать то, что вам нужно, и создать список размером 1 со скалярным значением в качестве первого элемента.

Также

my @a = undef;

делает то же самое, но первый слот - undef. То, что вы хотите, это

my @a = [1];
4 голосов
/ 27 мая 2010

Вот что, по-моему, вы хотели написать:

my $x = [[1]]; # reference to anon array containing
               # reference to anon array with one element

print $x->[0][0];

См. Также Руководство по структурам данных Perl .

3 голосов
/ 28 мая 2010

mobrule, Axeman и Sinan ответили на ваш вопрос: вы создали структуру данных глубиной 3 слоя вместо 2.

Я удивлен, что никто не предложил использовать базовую библиотеку Data :: Dumper , чтобы помочь понять вопросы структуры данных.

use Data::Dumper;

my @a = [[1]];
print Dumper \@a;

Это печатает:

$ VAR1 = [ [ [ 1 ] ] ];

В вашей ошибке использовался ссылочный конструктор массива [] вместо использования круглых скобок (или ничего). @a = ([1]);

Итак, почему Perl имеет странный синтаксис [] и {} для объявления ссылок на хеш и массивы?

Все сводится к тому, что Perl сглаживает списки. Это означает, что если вы скажете: @a = (@b, @c);, что @a назначено содержимое @b, объединенное с содержимым @c. Это то же самое, что и метод списка extend в Python. Если вы хотите, чтобы у @a было два элемента, вам нужно заставить их не расширяться. Вы делаете это, беря ссылку на каждый массив: @a = (\@b, \@c);. Это похоже на метод списка append в Python.

Если вы хотите создать анонимные вложенные структуры, вам нужно иметь возможность пометить их как хэши или массивы. Вот тут и появился синтаксис, о котором я упоминал выше.

Но что хорошего в выравнивании списков? Почему стоит использовать этот необычный синтаксис для создания ссылок на массивы и хеш, который отличается от синтаксиса, используемого для нормальной инициализации?

Уплощение списка означает, что вы можете легко собрать список параметров подпрограммы в переменной и затем передать их, не делая ничего хитрого: foo(@some_args, 5, @more_args);. См. Применить в википедии для получения информации о том, как эта концепция работает на других языках. Вы можете делать все другие приятные вещи с помощью map и других функций.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...