【问题标题】:List Assignment in Scalar Context标量上下文中的列表赋值
【发布时间】:2012-03-07 14:33:27
【问题描述】:

标量上下文中的列表赋值返回右侧元素的数量:

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

【问题讨论】:

  • 确实,不:如果左侧列表是在标量上下文中评估的事物,则值为undef。列表不是数组。
  • @darch,这没有任何意义。 ($hello, $there, $world)(和(7,8))不能在($hello, $there, $world) = (7,8) 的标量上下文中执行。如果需要,列表分配可以返回 3,但没有理由这样做。
  • 我准确地回应了“然后 [列表 ($hello, $there, $world)] 在标量上下文中求值”这句话。评估 my ($h, $t, $w) = (7, 8, undef); scalar ($h, $t, $w) 并查看列表不是数组。
  • @darcy scalar($h, $t, $w)scalar($w) 相同......这是一个序列运算符,而不是一个列表。实时调频:perldoc.perl.org/functions/scalar.html

标签: perl list variable-assignment scalar


【解决方案1】:

记录在perlop(赋值运算符部分的最后一句)中计算右侧的元素:

类似地,列表上下文中的列表赋值产生分配给的左值列表,而标量上下文中的列表赋值返回赋值右侧表达式产生的元素数。

这样做的原因是你可以这样写:

while (my ($key, $value) = each %hash) { ... }

如果它计算赋值左侧的元素数量,那将是一个无限循环。

如果您考虑一下,左侧的元素数量要么与右侧的相同,要么是一个常数(当您分配给标量列表时)。在第一种情况下,你计算哪一边没有区别,在第二种情况下,计算右手边更有用。

另一方面,在列表上下文中,赋值运算符返回左侧列表,因为它更有用。如果您在修改列表元素的上下文中使用它,您希望修改刚刚分配给的变量。

回复:您的评论在您的示例中,(7,8) 是一个二元素列表,这就是赋值运算符返回 2 的原因。当您将较短的列表分配给较长的标量列表时,在分配发生之前,右侧没有用undef“填充”。相反,从右侧列表中没有与它们关联的值的任何变量都将重置为其默认值。对于标量变量,即undef。对于数组,这是一个空数组。对于散列,这是一个空散列。

【讨论】:

  • 您的回答很有道理,我理解它为什么会这样工作,但我更感兴趣的是它是如何工作的。请参阅我对 ikegamis 帖子的评论。
  • @Brian,在列表上下文中,您获得左侧列表,但在标量上下文中,您获得右侧列表的计数。在这两种情况下,这是因为这是最有用的返回。有关详细信息,请参阅我的更新答案。
  • @Brian,Perl 中有许多函数和运算符在标量上下文中返回的内容与它们在列表上下文中返回的元素数量不同。您必须阅读文档才能了解函数或运算符将返回什么。
  • “我理解它为什么会这样工作,但我更感兴趣的是它是如何工作的。” ——这是一个毫无意义的陈述。它以这种方式工作,因为语言规范说它确实如此。它的工作原理是通过 perl 实现。
【解决方案2】:
对我来说,上下文影响评估哪一方似乎很奇怪:

它没有。列表赋值运算符的两边(操作数)都被评估,无论列表赋值是在标量上下文还是列表上下文中评估,都不会影响对操作数的评估。

列表赋值是在标量上下文还是列表上下文中求值只影响它返回的值。

我之前创建了Scalar vs List Assignment Operator,它试图阐明两个赋值运算符之间的区别以及它们在标量和列表上下文中的行为方式。

【讨论】:

  • 我编辑了那句话以澄清一点:It seems weird to me that context affects which part of the evaluated expression is returned: 我知道上下文不会影响评估,只会影响返回结果,但我想知道它是如何工作的。如果赋值的右侧被评估然后分配到左侧,那么为什么标量会得到 2?右侧评估为 3 元素列表,然后应将其分配给标量。这就像 perl 只是决定忽略优先规则并选择应该返回表达式的哪一部分。
  • 当然,除非my @greeting = (($hello, $there, $world) = (7,8)) 会给出@greeting (7,8) 而不是($hello, $there, $world),现在这对我来说更有意义。但是如果@greeting 得到($hello, $there, $world) 并且$greeting 得到(7,8) 的结果,那么这没有任何意义。
  • $greeting 没有得到(7,8) 的结果。事实上,$greeting 不可能得到这个(7,8) 的结果,因为这个(7,8) 求值为一个列表值,而一个列表值不能赋值给一个标量。@greeting$greeting 都得到列表分配的结果,根据上下文,它可以是“其 LHS 评估的值列表”或“其 RHS 评估的元素数量”。您似乎在暗示最好返回不同的东西而不给出任何理由来说明其他结果如何有用。
  • @ikegami,我认为他的意思是,如果标量上下文中的表达式返回它们将在列表上下文中返回的元素数量,则会更加一致。他是对的,它会更加一致。它只是没那么有用,而且 Perl 的目标是实用性而不是一致性。
  • @cjm,返回值的选择基于有用性。没有一致性。每个运算符返回不同的东西。这很好。操作员应该做不同的事情。在标量上下文中调用时,让每个运算符表现得好像被 (...)[0](...)[-1] 包围是非常愚蠢的,但这些是对所有运算符都有意义的唯一选择。
【解决方案3】:

为什么它评估右手边并产生 2,而不是评估新定义的列表并返回 3?

因为这是语言定义说它应该做的,因为这就是 Larry Wall 决定它应该做的。

在我看来,$hello 得到 7,$there 得到 8,$world 得到 undef,然后在标量上下文中评估该列表

不,perl 不能那样工作。您假设标量上下文只是通过计算列表结果中元素的数量将在列表上下文中获得的结果转换为标量,但这根本不对...标量上下文意味着操作(在这种情况下赋值)应该产生一个标量结果,并且通常有标量结果比列表上下文结果中的元素数量更有用,并且因运算符而异......你必须检查文档标量产生什么;它不统一。对于列表分配,标量值是右侧元素的数量,因为这比接收者的数量有用得多,接收者的数量是恒定的。例如,如果匹配产生结果,if (($a, $b) = $s =~ /$re/) 为真,而不是因为有两个接收者而始终为真。

对我来说,上下文影响评估的哪一部分似乎很奇怪 返回表达式

perl 中有很多更奇怪的东西。这种奇怪的感觉来自模型之间的不匹配......在这种情况下,您对正交性的期望以及您认为“标量上下文”是列表上的运算符,而 perl 的实用设计和“标量上下文”的现实 建立一个上下文,它决定了要产生什么结果。请注意,您可以编写自己的函数,根据调用的上下文产生完全不同的结果

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-07-01
    • 2011-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-27
    • 1970-01-01
    相关资源
    最近更新 更多