标量上下文中的列表赋值
标量上下文中的列表赋值返回右侧的元素数量:
scalar(my ($hello, $there, $world) = (7,8)); #evaluates to 2
为什么它计算右侧并生成 2,而不是计算新定义的列表并返回 3?
对我来说,似乎 $hello
得到 7,$there
得到 8,而 $world
得到 undef
,然后在标量上下文中计算该列表,结果为 3,因为这是列表中的元素数量 ($hello $there $world
)。对我来说,上下文影响返回计算表达式的哪一部分似乎很奇怪:
my $greeting = (($hello, $there, $world) = (7,8)); #2
my @greeting = (($hello, $there, $world) = (7,8));
my $greeting_length = @greeting; #3
A list assignment in scalar context returns the number of elements on the right hand side:
scalar(my ($hello, $there, $world) = (7,8)); #evaluates to 2
Why does it evaluate the right hand side and produce 2, instead of the newly defined list being evaluated and returning 3?
To me, it seems like $hello
gets 7, $there
gets 8, and $world
gets undef
, then that list is evaluated in scalar context, which would result in 3, as that is the number of elements in the list ($hello $there $world
). It seems weird to me that context affects which part of the evaluated expression is returned:
my $greeting = (($hello, $there, $world) = (7,8)); #2
my @greeting = (($hello, $there, $world) = (7,8));
my $greeting_length = @greeting; #3
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
据记录,在 perlop 中对右侧的元素进行计数(赋值运算符部分):
它这样工作的原因是这样你可以写这样的东西:
如果它计算赋值左侧的元素数量,那将是一个无限循环。
如果您考虑一下,左侧的元素数量要么与右侧相同,要么是一个常量(当您分配给标量列表时)。在第一种情况下,计算哪一侧没有区别,而在第二种情况下,计算右侧更有用。
另一方面,在列表上下文中,赋值运算符返回左侧列表,因为这更有用。如果您在修改列表元素的上下文中使用它,您需要修改刚刚分配的变量。
回复:您的评论 在您的示例中,
(7,8)
是一个二元素列表,这就是赋值运算符返回 2 的原因。当您将较短的列表分配给标量列表较长,在赋值之前右侧不会用undef
进行“填充”。相反,右侧列表中没有与其关联的值的任何变量都将重置为其默认值。对于标量变量,即undef
。对于数组来说,这是一个空数组。对于哈希值来说,这是一个空哈希值。It's documented to count the elements on the right in perlop (the last sentence in the Assignment Operators section):
The reason it works like that is so that you can write things like this:
If it counted the number of elements on the left hand side of the assignment, that would be an infinite loop.
If you think about it, the number of elements on the left hand side is either the same as on the right hand side or it's a constant (when you're assigning to a list of scalars). In the first case, it makes no difference which side you count, and in the second case, counting the right hand side is more useful.
On the other hand, in list context the assignment operator returns the left hand list, because that's more useful. If you use it in a context that modifies the list elements, you want to modify the variables that were just assigned to.
Re: your comment In your example,
(7,8)
is a two-element list, which is why the assignment operator returns 2. When you assign a shorter list to a longer list of scalars, the right hand side is not "padded out" withundef
before the assignment happens. Instead, any variables that did not have a value associated with them from the right hand list are reset to their default value. For a scalar variable, that'sundef
. For arrays, that's an empty array. For hashes, that's an empty hash.事实并非如此。列表赋值运算符的两侧(操作数)都会被求值,并且列表赋值是在标量上下文中还是在列表上下文中求值,都不会影响操作数的求值。
列表赋值是在标量上下文还是列表上下文中计算仅影响它返回的值。
我之前创建了标量与列表赋值运算符,它试图阐明两个赋值运算符之间的差异以及它们的行为方式在标量和列表上下文中。
It doesn't. Both sides (operands) of the list assignment operator evaluated, and whether the list assignment is evaluated in scalar context or list context does not affect the evaluation of the operands whatsoever.
Whether a list assignment is evaluated in scalar context or list context only affects the value it returns.
I have previously created Scalar vs List Assignment Operator, which attempts to make clear the differences between the two assignment operators and how they behave in scalar and list context.
因为这就是语言定义所说的它应该做的事情,因为这就是拉里·沃尔决定它应该做的事情。
不,perl 不那样工作。您假设标量上下文只是通过计算列表结果中的元素数量将在列表上下文中获得的结果转换为标量,但这根本不正确......标量上下文意味着一个操作(在这种情况下赋值)应该产生一个标量结果,并且通常有标量结果比列表上下文结果中的元素数量更有用,并且每个操作符都不同......你必须检查文档对于标量产生什么;它不统一。对于列表分配,标量值是右侧元素的数量,因为它比接收器的数量(恒定)有用得多。例如,如果匹配产生结果,则
if (($a, $b) = $s =~ /$re/)
为 true,而不是因为有两个接收者而始终为 true。Perl 中还有更奇怪的事情。这种奇怪的感觉来自于模型之间的不匹配......在这种情况下,你对正交性的期望和你对“标量上下文”是列表上的运算符的信念,与 Perl 的实用设计和“标量上下文”的现实建立一个上下文来决定产生什么结果。请注意,您可以编写自己的函数,根据调用的上下文产生完全不同的结果。
Because that's what the language definition says it should do, because that's what Larry Wall decided it should do.
No, perl does not work that way. You're assuming that scalar context is just a conversion of the result that would have been obtained in list context to a scalar by counting the number of elements in the list result, but that's simply not right ... scalar context means that an operation (in this case assignment) should produce a scalar result, and there are often scalar results that are more useful than just the number of elements in the list context result, and that varies from operator to operator ... you have to check the documentation for what scalar produces; it's not uniform. For list assignment, the scalar value is the number of elements on the right side, because that's vastly more useful than the number of receivers, which is constant. e.g.,
if (($a, $b) = $s =~ /$re/)
is true if the match produced results, as opposed to always being true because there are two receivers.There are far weirder things in perl. That feeling of weirdness comes from a mismatch between models ... in this case your expectation of orthogonality and your belief that "scalar context" is an operator on lists, vs. perl's pragmatic design and the reality that "scalar context" establishes a context which determines what result to produce. Note that you can write your own functions that produce completely different results depending on the context of the call.