Использование my с круглыми скобками и только одна переменная
Иногда я вижу код Perl следующим образом:
my ( $variable ) = blah....
В чем смысл размещения круглых скобок вокруг одной переменной? Я думал, что скобки используются только при объявлении нескольких переменных, например:
my ( $var1, $var2, $var3 ) = blah...
Ответы
Ответ 1
Существует несколько сценариев, когда есть разница:
-
Когда массив находится на правой стороне
my @array = ('a', 'b', 'c');
my $variable = @array; # 3 size of @array
my ($variable) = @array; # 'a' $array[0]
-
Когда список находится на правой стороне
my $variable = qw/ a b c d /; # 'd' last item of the list
my ($variable) = qw/ a b c d /; # 'a' first item of the list
-
Подпрограмма с переменным (массив/скаляр) возвращаемое значение
sub myFunction {
...
return (wantarray() ? @array : $scalar);
}
my $variable = myFunction(...); # $scalar from the subroutine
my ($variable) = myFunction(...); # $array[0] from the subroutine
Ответ 2
Скобки создают контекст списка, который влияет на то, как оценивается правая сторона присваивания.
Сравнение
my $x = grep { /s/ } qw(apples bananas cherries);
print $x;
с
my ($x) = grep { /s/ } qw(apples bananas cherries);
print $x;
Вы часто будете использовать эту конструкцию, когда вы просто хотите захватить первый элемент списка и отбросить остальные.
Ответ 3
Я не Perl pro (во что бы то ни стало, я не), но AFAIK это связано со списками.
Perl имеет разные контексты (скалярный, список). Использование ($var)
переключается в контекст списка, $var
- это скалярный контекст.
my $var = (1, 2, 4); # $var = 4 (last element)
my ($var) = (1, 2, 4); # $var = 1
Пожалуйста, снимите этот ответ, если это абсолютно неправильно:)
Ответ 4
Вы смешиваете две разные вещи. Во-первых, при использовании my
для объявления нескольких переменных вам нужно использовать круглые скобки:
my $foo, $bar;
Не работает, так как считается, что это два разных оператора:
my $foo;
$bar;
Итак, вам нужны скобки для группировки аргумента в список аргументов функции my
:
my($foo, $bar);
Во-вторых, у вас есть явная группировка для вызова контекста списка:
$foo, $bar = "a", "b"; # wrong!
Будут рассмотрены три отдельных заявления:
$foo;
$bar = "a";
"b";
Но если вы используете круглые скобки для группировки $foo
и $bar
в список, оператор присваивания будет использовать контекст списка:
($foo, $bar) = ("a", "b");
Любопытно, что если вы удалите скобки RHS, вы также столкнетесь с hickup:
($foo, $bar) = "a", "b"; # Useless use of a constant (b) in void context
Но это связано с тем, что оператор =
имеет более высокий приоритет, чем запятая ,
, которую вы можете увидеть в perlop. Если вы попытаетесь:
my @array = ("a", "b");
($foo, $bar) = @array;
Вы получите желаемое поведение без круглых скобок.
Теперь, чтобы заполнить круг, удалим контекст списка в приведенном выше примере и посмотрим, что произойдет:
my @array = ("a", "b");
$foo = @array;
print $foo;
Это печатает 2
, потому что массив оценивается в скалярном контексте, а массивы в скалярном контексте возвращают количество элементов, которые они содержат. В этом случае это 2
.
Следовательно, такие выражения, как контекст контекста использования:
my ($foo) = @array; # $foo is set to $array[0], first array element
my ($bar) = ("a", "b", "c"); # $bar is set to "a", first list element
Это способ переопределить скалярный контекст, который подразумевается в скалярном присваивании. Для сравнения, эти назначения находятся в скалярном контексте:
my $foo = @array; # $foo is set to the number of elements in the array
my $bar = ("a", "b", "c"); # $bar is set to "c", last list element
Ответ 5
Я разместил подробное объяснение по этому вопросу на другом сайте.
[Я не могу опубликовать его здесь. StackOverflow не поддерживает таблицы. Не то, чтобы у кого-то обычно была проблема с внешним подключением к документации.]