Скалярный и список контекста в Perl - PullRequest
0 голосов
/ 26 января 2011
1 @backwards = reverse qw(yabba dabba doo);
2 $backwards = reverse qw(yabba dabba doo);
3 
4 print @backwards; #gives doodabbayabba
5 print $backwards."\n"; #gives oodabbadabbay
6 print @backwards."\n"; #gives 3

В приведенном выше коде почему line 6 дает 3 в качестве выхода?Почему он конвертируется в скалярный контекст, если он объединен с \ n?

Спасибо

Ответы [ 3 ]

8 голосов
/ 26 января 2011

Строка 6 дает 3, потому что оператор . налагает скалярный контекст на оба его операнда, а @backwards в скалярном контексте дает 3 (потому что любой массив в скалярном контексте сообщает количество элементов в нем).

Попытка:

print "@backwards\n";

Чтобы объединить элементы в массиве, используйте join:

print join(', ', @backwards) . "\n";
7 голосов
/ 26 января 2011

Ваш вопрос в конечном итоге «почему @backwards находится в скалярном контексте в строке 6», что Напрашивается вопрос: «Как я могу определить контекст термина?».

Контекст определяется термином «что вокруг» (то есть его «контекст»).

Как я могу определить контекст термина? Глядя на оператора / функцию, которая использует термин.

Какие шаги вы могли бы выполнить, чтобы выяснить контекст для @backwards самостоятельно, если вы у вас не было людей, которые могли бы рассказать вам о его контексте?

Здесь мы имеем

print @backwards."\n"

так что есть два оператора / функции. Как мы узнаем, какой из них предоставляет контекст в @ назад? Консультируясь с приоритетом. Около вершины perlop.pod у нас есть Perl's таблица приоритетов (print - «оператор списка»):

left    terms and list operators (leftward)
...
left    + - .
...
nonassoc    list operators (rightward)

О, отлично, теперь нам нужно знать, направлен ли отпечаток влево или вправо. По консультации раздел «Термины и операторы списка (влево)» в perlop (сразу после список приоритетов) мы видим, что печать здесь справа, потому что мы не приложили его аргументы в скобках.

Таким образом, конкатенация имеет более высокий приоритет, поэтому конкатенация предоставляет контекст для @ backwards.

Следующим шагом является проверка документов (снова perlop) для объединения:

Binary "." concatenates two strings.

Строки являются скалярами, поэтому двоичные "." объединяет два скаляра.

И, наконец, оно у нас есть!

@ backwards имеет скалярный контекст, потому что конкатенация обеспечивает скалярный контекст для каждый из его операндов.

Woo. Это было легко, не так ли: -)

4 голосов
/ 26 января 2011

Контекст хитрый.И иногда пара пикселей может иметь все значение.Рассмотрим следующие две строки:

print localtime, "\n";
print localtime. "\n";

Вы заметили разницу?

Эти два утверждения выглядят действительно похожими.Но то, что происходит в двух случаях, очень разное.

В первом утверждении print передается список аргументов.И документация для печати говорит, что она навязывает контекст списка своим аргументам.Поэтому вызов localtime оценивается в контексте списка, и функция возвращает список чисел.

Во втором операторе print получает единственный аргумент.Этот аргумент представляет собой строку, созданную путем объединения результатов вызова localtime с символом перевода строки.Оператор конкатенации накладывает скалярный контекст на оба его операнда.Поэтому вызов localtime возвращает текущее время в удобочитаемом формате строки.Затем эта строка объединяется с символом новой строки, и полученная строка передается на печать.Вызов print все еще оценивает свой аргумент в контексте списка, но этот контекст не имеет значения для способа интерпретации однострочного аргумента.

Для другого, аналогичного, взгляните на более странные углы контекста в Perl, смотрите вопрос Я разместил в своем блоге пару дней назад.Я опубликую решение через несколько дней.

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