Поскольку Юджин и Муген уже хорошо ответили на этот вопрос хорошими примерами, я собираюсь изложить некоторые концепции, а затем задать некоторые концептуальные вопросы ОП, чтобы посмотреть, поможет ли это пролить свет на некоторые концепции Perl.
Первая концепция заключается в том, что означают сигилы $
и @
(здесь мы не будем обсуждать %
).@
означает несколько предметов (сказано "эти вещи").$
означает один предмет (сказал "эта вещь").Чтобы получить первый элемент массива @a
, вы можете сделать $first = $a[0]
, получить последний элемент: $last = $a[-1]
.NB не @a[0]
или @a[-1]
.Вы можете нарезать, выполнив @shorter = @longer[1,2]
.
Вторая концепция - это различие между пустым, скалярным и списочным контекстом.В Perl есть концепция контекста, в котором используются ваши контейнеры (скаляры, массивы и т. Д.).Простой способ убедиться в том, что если вы сохраняете список (мы перейдем к нему) как массив @array = ("cow", "sheep", "llama")
, тогда мы сохраняем массив как скаляр $size = @array
, мы получаем длину массива.Мы также можем форсировать это поведение, используя оператор scalar
, такой как print scalar @array
.Я скажу это еще раз для ясности: массив (не список) в скалярном контексте будет возвращать не элемент (как список), а скорее длину массива.
Помните, что перед вамииспользуйте символ $
, если вы ожидаете только один предмет, то есть $first = $a[0]
.Таким образом, вы знаете, что находитесь в скалярном контексте.Теперь, когда вы вызываете $length = @array
, вы можете ясно видеть, что вы вызываете массив в скалярном контексте, и, таким образом, вы запускаете специальное свойство массива в контексте списка, вы получаете его длину.
Это имеет другой хорошийфункция для тестирования, если есть элемент в массиве.print '@array contains items' if @array; print '@array is empty' unless @array
.Тесты if /лачков заставляют скалярный контекст для массива, поэтому if видит длину массива, а не его элементы.Поскольку все числовые значения являются «истинными», кроме нуля, если массив имеет ненулевую длину, оператор, если @array
оценивается как истинный, и вы получаете оператор печати.
Пустой контекст означает, что возвращаемое значениенекоторые операции игнорируются.Полезной операцией в пустом контексте может быть что-то вроде увеличения.$n = 1; $n++; print $n;
В этом примере $n++
(приращение после возврата) находилось в пустом контексте, поскольку его возвращаемое значение «1» не использовалось (сохранено, напечатано и т. Д.).
Третья концепция - это разница междусписок и массив.Список - это упорядоченный набор значений, а массив - это контейнер, который содержит упорядоченный набор значений.Вы можете увидеть разницу, например, в гимнастике, которую нужно сделать, чтобы получить определенный элемент после использования sort
без предварительного сохранения результата (например, попробуйте pop sort { $a cmp $b } @array
, который не работает, потому что pop не действует только на список, толькомассив).
Теперь мы можем спросить, когда вы попробуете свои примеры, что бы вы хотели, чтобы Perl делал в этих случаях?Как уже говорили другие, это зависит от приоритета.
В вашем первом примере, поскольку оператор =
имеет более высокий приоритет, чем ,
, вы фактически не присваивали список переменной, вы сделали что-то более похожее на ($a = "b"), ("c")
, что эффективноничего со строкой "с".На самом деле это было названо в пустом контексте.С включенными предупреждениями, поскольку эта операция ничего не выполняет, Perl пытается предупредить вас, что вы, вероятно, не хотели делать это с сообщением: Useless use of a constant in void context
.
Теперь, что бы вы хотели, чтобы Perl делалкогда вы пытаетесь сохранить список в скаляре (или используете список в скалярном контексте)?Он не будет хранить длину списка, это только поведение массива.Поэтому он должен хранить одно из значений в списке.Хотя я знаю, что это не является канонически верным, этот пример очень близок к тому, что происходит.
my @animals = ("cow", "sheep", "llama");
my $return;
foreach my $animal (@animals) {
$return = $animal;
}
print $return;
И, следовательно, вы получаете последний элемент списка (каноническое отличие состоит в том, что предыдущие значения никогда не сохранялись тогдаперезаписан, однако логика аналогична).
Есть способы сохранить что-то, что выглядит как список в скаляре, но это включает ссылки.Подробнее об этом читайте в perldoc perlreftut
.
Надеюсь, это немного прояснит ситуацию.В заключение я скажу, что пока вы не овладеете правилами приоритета Perl, никогда не помешает поставить явные скобки для списков и аргументов функции.