开发者

How do parentheses work in Perl 5?

开发者 https://www.devze.com 2023-03-20 14:53 出处:网络
Here\'s a Devel::REPL session (my Perl version is v5.10.1). Could you explain the results, please? 0:main$ my $x = 1,2,4

Here's a Devel::REPL session (my Perl version is v5.10.1). Could you explain the results, please?

0:main$ my $x = 1,2,4
[
  1,
  2,
  4
]

0:main$ my $y = (1,2,4)
Useless use of a constant in void context at (eval 296) line 8.
4

I'm just beginning learning Perl and still have troubles grokking the contexts. Anyways, I think that I understand why the second assignment does what it does. That's because we've got a scalar context, that's why no list get constructed at all, and we just end up executing the comma operator repeatedly, whilst that opetator simply returns its right operand. Right?

However, what's wrong with the first assignment? Shouldn't 开发者_运维百科it be equivalent to the second one? At some point, I thought that parentheses don't provide any magic semantics to build lists - they just group the elements together, and if the elements end up being used in a list context, they just get transformed to a list. Apparently, that's not true.

Well, ok. What is the special role of the parentheses then?


Devel::REPL is evaluating each input line in list context, and then printing the resultant list. So effectively the first line is something like:

 say join ', ' => do {my $x = 1, 2, 4}

Which is parsed as:

 say join ', ' => do {(my $x = 1), (2), (4)}

And so the REPL prints "1, 2, 4" since it received 3 values from the do block.

The second line is:

 say join ', ' => do {my $x = (1, 2, 4)}

Which is parsed as:

 say join ', ' => do {(my $x = scalar(1, 2, 4))}

The list in scalar context returns its last element, which is assigned to $x and then returned by the do block, subsequently printing "4".


I think the behavior of the first statement is a result of Devel::REPL, but I don't have it available to me at the moment to test that assumption.

Parentheses in Perl primarily adjust precedence. They can also adjust how the parser sees some statements, but that's not the case here. The = has a higher precedence than ,, so in the first statement, if Devel::REPL evaluates statements in list context, is parsed as a list where the first element is the result of the assignment of 1 to $x and the second and third values are 2 and 4. In the second precedence has been changed and as a result context has changed so that the , is in scalar context and 4 is assigned to $x.

$ perl -MO=Deparse,-p -e 'my $x = 1,2,4'
((my $x = 1), '???', '???');
-e syntax OK

$ perl -MO=Deparse,-p -e 'my $x = (1,2,4)'
(my $x = ('???', '???', 4));
-e syntax OK

I would bet if you ran scalar(my $x = 1,2,4) in Devel::REPL the result would be 4 and $x would equal 1.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号