В чем разница между контекстами scalar и list в Perl?
Вопрос
В чем разница между контекстами scalar и list в Perl и имеет ли это какие-либо параллели в других языках, таких как Java или Javascript?
Решение
Различные операторы в Perl зависят от контекста и выдают разные результаты в списке и скалярном контексте.
Например:
my(@array) = (1, 2, 4, 8, 16);
my($first) = @array;
my(@copy1) = @array;
my @copy2 = @array;
my $count = @array;
print "array: @array\n";
print "first: $first\n";
print "copy1: @copy1\n";
print "copy2: @copy2\n";
print "count: $count\n";
Выходной сигнал:
array: 1 2 4 8 16
first: 1
copy1: 1 2 4 8 16
copy2: 1 2 4 8 16
count: 5
Сейчас:
$first
содержит 1 (первый элемент массива), поскольку круглые скобки вmy($first)
предоставьте контекст массива, но в нем есть место только для одного значения$first
.- и то, и другое
@copy1
и@copy2
содержать копию@array
, - и
$count
содержит 5, потому что это скалярный контекст, и@array
вычисляет количество элементов в массиве в скалярном контексте.
Можно было бы также построить более сложные примеры (результаты являются упражнением для читателя).:
my($item1, $item2, @rest) = @array;
my(@copy3, @copy4) = @array, @array;
В других известных мне языках нет прямой параллели со списком и скалярным контекстом.
Другие советы
Скалярный контекст - это то, что вы получаете, когда ищете одно значение.Контекст списка - это то, что вы получаете, когда ищете несколько значений.Одно из наиболее распространенных мест, где можно увидеть различие, - это при работе с массивами:
@x = @array; # copy an array
$x = @array; # get the number of elements in an array
Другие операторы и функции также зависят от контекста:
$x = 'abc' =~ /(\w+)/; # $x = 1
($x) = 'abc' =~ /(\w+)/; # $x = 'abc'
@x = localtime(); # (seconds, minutes, hours...)
$x = localtime(); # 'Thu Dec 18 10:02:17 2008'
То, как оператор (или функция) ведет себя в данном контексте, зависит от оператора.Не существует общих правил относительно того, как должны вести себя вещи.
Вы можете сделать свои собственные подпрограммы контекстно-зависимыми, используя wantarray
функция для определения контекста вызова.Вы можете принудительно вычислить выражение в скалярном контексте, используя scalar
ключевое слово.
В дополнение к контекстам scalar и list вы также увидите контексты "void" (ожидаемое возвращаемое значение отсутствует) и "boolean" (ожидаемое значение true / false), упомянутые в документации.
Это просто означает, что тип данных будет оцениваться на основе режима работы.Например, присвоение скаляру означает, что правая сторона будет оцениваться как скаляр.
Я думаю, что лучший способ понять контекст - это узнать о wantarray.Итак, представьте, что = - это подпрограмма , которая реализует wantarray:
sub = {
return if ( ! defined wantarray ); # void: just return (doesn't make sense for =)
return @_ if ( wantarray ); # list: return the array
return $#_ + 1; # scalar: return the count of the @_
}
Примеры в этот пост работайте так, как если бы вышеупомянутая подпрограмма вызывалась путем передачи правой части в качестве параметра.
Что касается параллелей в других языках, да, я по-прежнему утверждаю, что практически каждый язык поддерживает что-то подобное.Полиморфизм одинаков во всех языках OO.Другой пример: Java преобразует объекты в строку в определенных контекстах.И каждый нетипизированный скриптовый язык, который я использовал, имеет схожие концепции.