В чем разница между скалярным и списочным контекстами в Perl? - PullRequest
5 голосов
/ 18 декабря 2008

В чем разница между скалярным и списочным контекстами в Perl, и имеет ли это какую-либо параллель в других языках, таких как Java или Javascript?

Ответы [ 3 ]

11 голосов
/ 18 декабря 2008

Различные операторы в 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;

В других известных мне языках нет прямой параллели со списком и скалярным контекстом.

4 голосов
/ 18 декабря 2008

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

@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.

Помимо контекстов скаляра и списка, вы также увидите контексты «void» (ожидаемое возвращаемое значение) и «логическое» (ожидаемое значение true / false), упомянутые в документации.

0 голосов
/ 18 декабря 2008

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

Я думаю, что лучшее средство понимания контекста - это изучение хотаррей. Итак, представьте, что = это подпрограмма, которая реализует 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 @_
}

Примеры в этом посте работают так, как будто вышеупомянутая подпрограмма вызывается передачей правой части в качестве параметра.

Что касается параллелей в других языках, да, я все еще утверждаю, что практически каждый язык поддерживает нечто подобное. Полиморфизм одинаков во всех ОО языках. Другой пример, Java преобразует объекты в строку в определенных контекстах. И каждый нетипизированный язык сценариев, который я использовал, имеет сходные понятия.

...