Perl: Почему вы можете использовать @ или $ при доступе к определенному элементу в массиве? - PullRequest
0 голосов
/ 11 декабря 2018

Я начинающий пользователь Perl и не смог найти удовлетворительного ответа

my @foo = ("foo","bar")
print "@foo[0]"
foo
print "$foo[1]"
bar

Не только @foo[0] работает, как ожидалось, но $foo[1] также выводит строку.

Почему?Это даже когда use strict включено.

Ответы [ 3 ]

0 голосов
/ 12 декабря 2018

Символы Perl сообщают вам, как вы обрабатываете данные, и только слабо относятся к типу переменной.Вместо того, чтобы думать о том, что является , подумайте о том, что делает .Это глаголы над существительными в Perl:

  • $ использует один элемент
  • @ использует несколько элементов
  • % использует пары

Скалярная переменная $foo представляет собой отдельный элемент и использует символ $.Поскольку для одного элемента нет кратных чисел или пар, другие сигилы не вступают в игру.

Переменная массива @foo - это потенциально много элементов, а @ относится ко всем этим элементам.все вместе.$foo[INDEX] относится к одному элементу в массиве и использует символ $.Вы можете ссылаться на несколько элементов с фрагментом массива, например @foo[INDEX,INDEX2,...], и для этого вы используете @.Ваш вопрос посвящен вырожденному случаю среза одного элемента, @foo[INDEX].Это работает, но это в контексте списка.Иногда это ведет себя по-разному.

Хеш-переменная %foo представляет собой набор пар ключ-значение.Чтобы получить одно значение, вы снова используете $, например $foo{KEY}.Вы также можете получить более одного значения с помощью хеш-фрагмента, используя @, потому что это несколько значений, например, @hash{KEY1,KEY2,...}.

И вот недавняя разработка: Perl 5.20 представляет «Ключ /Ценные ломтики ».Вы можете получить фрагмент хеша из массива или хеша.%array[INDEX1,INDEX2] или %hash{KEY1,KEY2}.Они возвращают список пар ключ-значение.В случае массива ключами являются индексы.

Для массивов и хэшей с доступом к одному элементу или срезом любого типа тип переменной известен по индексирующему символу: массивы используют [], а хэши используют {}.И вот еще одна интересная проблема: эти разделители предоставляют скалярный или списочный контекст в зависимости от одного или (потенциально) нескольких элементов.

0 голосов
/ 12 декабря 2018

И @foo[0], и $foo[1] являются допустимыми конструкциями Perl.

$foo[EXPR] (где EXPR - произвольное выражение, вычисленное в скалярном контексте), возвращает один элемент, указанный в результате выражения.

@foo[LIST] (где LIST - произвольное выражение, вычисленное в контексте списка), возвращает каждый элемент, указанный в результате выражения.

(В отличие от других сообщений, такого нетвещь как $foo[LIST] в Perl. При использовании $foo[...] выражение всегда вычисляется в скалярном контексте.)

Хотя @foo[1] является допустимым выражением, опыт показывает, что эта конструкция обычно используется неправильно,когда было бы более уместно сказать $foo[1].Поэтому предупреждение - не исключение - выдается, когда предупреждения включены, и вы используете эту конструкцию.

Что это означает:

my @foo = ( "foo", "bar", "baz" );

$foo[0]        0 eval'ed in scalar cx.  Returns scalar "foo".             ok
@foo[1]        1 eval'ed in list cx.    Returns scalar "bar".             Weird. Warns.
@foo[0,2]    0,2 eval'ed in list cx.    Returns scalars "foo" and "baz".  ok
$foo[0,2]    0,2 eval'ed in scalar cx.  Returns scalar "baz".             Wrong. Warns.
$foo[@foo]  @foo eval'ed in scalar cx.  Returns undef.                    Probably wrong.

Единственная причина, по которой я мог придуматьиспользовать @foo[SCALAR] в качестве lvalue где-то, что различает скалярный / списочный контекст.Предположим, что

sub bar { wantarray ? (42,19) : 101 }

$foo[0] = bar(); присвоит значение 101 1-му элементу @foo, но @foo[0] = bar(); присвоит значение 42.Вместо этого было бы гораздо более распространенным использовать ($foo[0]) = bar().


Части поста Защищено авторским правом mob на тех же условиях, что и этот сайт.

Эта публикация посвящена многочисленным проблемам мобов. post , включая 1) неправильное использование LIST для обозначения чего-то иного, чем произвольное выражение в контексте списка, 2) притворяется, что parens создает списки, 3) притворяется, что есть разница между скалярами возврата и возвратомсписок и 4) делая вид, что нет такой вещи, как нефатальная ошибка.

0 голосов
/ 12 декабря 2018

И @foo[0], и $foo[1] являются допустимыми конструкциями Perl.

$foo[$n], или, в более общем смысле, $foo[EXPR], это скалярный элемент, представляющий $n -ую (с началом индексав 0) элемент массива @foo (или все, что EXPR оценивает до).

@foo[LIST] представляет собой срез массива , набор элементов @foo указан какиндексы в LIST.Когда LIST имеет один элемент, такой как @foo[0], тогда @foo[LIST] является списком с одним элементом.

Хотя @foo[1] является допустимым выражением, опыт показывает, что эта конструкция обычно используется неправильно,когда было бы более уместно сказать $foo[1].Поэтому предупреждение - не ошибка - выдается, когда предупреждения включены, и вы используете эту конструкцию.

$foo[LIST] также является допустимым выражением в Perl.Просто Perl оценит LIST в скалярном контексте и вернет элемент @foo, соответствующий этой оценке, а не список элементов.

@foo = ("foo","bar","baz");
$foo[0]     returns the scalar "foo"
@foo[1]     returns the list ("bar") (and issues warning)
@foo[0,2]   returns the list ("foo","baz")
$foo[0,2]   returns "baz"   ($foo[0,2] evaluates to $foo[2], and issues warning)
$foo[@foo]  returns undef   (evaluates to $foo[scalar @foo] => $foo[3])

Диверсия: единственная причина, по которой яможет придумать, чтобы использовать @foo[SCALAR] в качестве lvalue где-то, что различает скаляр / контекст списка.Предположим, что

sub bar { wantarray ? (42,19) : 101 }

$foo[0] = bar(); присвоит значение 101 1-му элементу @foo, но @foo[0] = bar() присвоит значение 42.Но даже это не то, чего нельзя достичь, сказав ($foo[0]) = bar(), если только вы не играете в гольф.

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