Скалярный против контекста списка в Perl - PullRequest
3 голосов
/ 02 марта 2011

Я нашел пример в книге О'Рейли немного странным:

@backwards = reverse qw/ yabba dabba doo /;
print "list context: @backwards\n";
$backward = reverse qw/ yabba dabba doo /;
print "scalar1 context: $backward\n";
$notbackward = qw/ yabba dabba doo /;
print "scalar2 context: $notbackward\n";
print "print context: ",reverse qw/ yabba dabba doo /;
print "\n";

Вывод:

list context: doo dabba yabba
scalar1 context: oodabbadabbay
scalar2 context: doo
print context: doodabbayabba

Тот, которого я не понимаю, это scalar1context:

В книге сказано, что «перевернуть что-то» дает контекст списка, поэтому я думаю, qw/ yabba dabba doo / рассматривается как список, а reverse qw/ yabba dabba doo / как («doo», «dabba», «yabba»).

Итак, $backward = something, что подразумевает что-то скалярное, поэтому я ожидал результата 'doo dabba yabba', но он отличается: 'oodabbadabbay'.причина была в том, что нельзя установить список в скаляр напрямую.Итак, я сделал тест scalar2: печатается только последний элемент в списке.Зачем?Почему не в тесте scalar1?

Как работает вывод скалярных тестов?

Ответы [ 4 ]

10 голосов
/ 02 марта 2011

Прежде всего, qw/ yabba dabba doo / - это просто синтаксический сахар для ('yabba', 'dabba', 'doo').Они означают одно и то же.

Функция reverse принимает список.В контексте списка он переворачивает список.В скалярном контексте он делает join('', @list), а затем переворачивает символы в этой строке и возвращает ее.

Помните, что

$backward = reverse qw/ yabba dabba doo /;
$notbackward = qw/ yabba dabba doo /;

означает

$backward = reverse ('yabba', 'dabba', 'doo');
$notbackward = ('yabba', 'dabba', 'doo');

The reverse функция предоставляет контекст списка, а $notbackward = дает нам скалярный контекст.Это означает, что оператор запятой находится в контексте списка в первой строке и скалярный контекст во второй.В контексте списка оператор запятой создает список.В скалярном контексте он оценивает оба операнда и возвращает правый.Это означает, что значение ('yabba', 'dabba', 'doo') в скалярном контексте равно 'doo', и это то, что присвоено $notbackward.

7 голосов
/ 02 марта 2011

Все функции Perl, в том числе любые sub, которые вы определяете, могут определять, вызываются ли они в "скалярном" или "списочном" контексте , и есть много функций, которые изменяют свое поведение на основании этого контекста.

Существует очень мало соглашений, кроме «Что я имею в виду», о том, когда и как функция обрабатывает два контекста по-разному (в этом целом потоке на perlmonks есть хорошее обсуждение этих проблем), поэтому нужно полагаться на документацию каждой функции, чтобы угадать, что функция будет делать в определенном контексте.

Специально для ваших четырех примеров,

1. @backwards = reverse qw/ yabba dabba doo /
2. $backward = reverse qw/ yabba dabba doo /
3. $notbackward = qw/ yabba dabba doo /;
4. print ..., reverse qw/ yabba dabba doo /;

поведение

1. reverse function, list context:     returns list of the elements in reverse order

2. reverse function, scalar context:   concatenate argument list to a string,
                                       return reverse of that string

3. list assignment to scalar:          returns last element in list (*)

4. also reverse function, list context    same as #1

(*) - назначение списка примечаний для скаляра отличается от массива назначение для скаляра - это одно из наиболее важных различий между списками и массивами :

@a = ("x", "y", "z");  $n = @a;   # array assignment,  $n is array size, or "3"
$n = ("x", "y", "z");             # list assignment,   $n is last element, or "z"
3 голосов
/ 02 марта 2011

Для строки:

$backward = reverse qw/ yabba dabba doo /;

Вы запрашиваете скаляр здесь с обратной стороны.Perldoc для reverse говорит:

В скалярном контексте объединяет элементы LIST и возвращает строковое значение со всеми символами в обратном порядке.

Таким образом, он возвращает каждыйбукв поменялись местами.

Для $ notbackward = qw / yabba dabba doo /;perldoc для qw // говорит:

Оценивает список слов, извлеченных из STRING, используя встроенный пробел в качестве разделителей слов.Его можно понимать как приблизительно эквивалентное:

               split(’ ’, q/STRING/);

, отличия в том, что он генерирует реальный список во время компиляции, а в скалярном контексте возвращает последний элемент в списке.

Таким образом, запрос скаляра возвращает только последний элемент в списке.

0 голосов
/ 03 марта 2011

Чтобы упростить другие ответы, на самом деле обратное делает две разные вещи: обращение к списку и обращение к строке.

Это оказалось настолько запутанным, что perl6 разделяет их на функции с разными именами.

...