【问题标题】:List or scalar context when returning an array or list with a single element返回具有单个元素的数组或列表时的列表或标量上下文
【发布时间】:2019-04-14 12:40:39
【问题描述】:

我有一个函数func,它可以返回单个值或值列表,具体取决于函数的调用方式。所以对于这个特定的函数,调用者会知道什么时候只期望一个返回值,因此希望使用更简单的语法my $var = func( ... ) 而不是my ($var) = func( ... )。问题在于,在某些情况下,单个值会转换为具有一个元素的列表/数组的大小,而在某些情况下则不会。例如:

use feature qw(say);
use strict;
use warnings;

for (1..4) {
    no strict 'refs';
    my $a = &{"func".$_}();
    say $a;
}

sub func1 {
    return ("Hi");
}

sub func2 {
    my @a = ("Hi");
    return @a;
}

sub func3 {
    my @a = ("Hi");
    return (@a);
}

sub func4 {
    my @a = ("Hi");
    return (pop @a);
}

给出输出:

Hi
1
1
Hi

为什么我在某些情况下得到 1 而在其他情况下得到"Hi"

【问题讨论】:

  • 在两种中间情况下,您返回的是一个 array。标量上下文中数组的标准行为是返回元素的数量。 "Hi" 是标量,pop 也是。

标签: perl


【解决方案1】:

返回表达式在与函数本身相同的上下文中进行评估。 Here 是一个非常全面的列表,列出了在标量上下文中返回的内容。

这里适用:

  • func1:字符串字面量不关心上下文。 "Hi" 计算为字符串 Hi,因此 func1 返回 Hi

  • func2:在标量上下文中,@a 计算为 @a 中的元素数,因此 func2 返回 1

  • func3:在标量上下文中,@a 计算为@a 中的元素数,因此func3 返回1

  • func4: pop 不关心上下文。 pop(@a) 计算出被移除的元素(如果@a 为空,则为 undef),所以func4 返回Hi

请注意,括号只是覆盖优先级,这对您的任何示例都没有影响。

你想要

sub func {
   my @a = ...;
   return wantarray ? @a : $a[-1];
}

如果你想聪明一点,你也可以使用以下方法,因为如果在列表上下文中返回,标量上下文中的切片会返回最后一个元素:

sub func {
   my @a = ...;
   return @a[0..$#a];
}

【讨论】:

  • 谢谢,也许我现在理解得更好了。在给出逗号之前,您不会创建列表。那么("Hi") 不是列表,而("Hi", "I") 是列表?
  • @Håkon Hægland,“列表”是一个非常通用的词。在 pilcrow 的引用中,“list”指的是列表运算符,也称为逗号运算符。所以"Hi" 不是列表,但"Hi", "I" 是。 (Parens 只是改变优先级。) // List 通常也指子或函数返回的内容。它只是意味着“一些标量”。 // 在列表上下文中,列表/逗号运算符"Hi", "I" 返回一个由两个标量组成的列表。与所有其他运算符一样,列表/逗号运算符 "Hi", "I" 在标量上下文中返回单个标量。
  • s/返回一个由两个标量组成的列表\K/(这是一种奇特的说法,它返回两个标量)/
【解决方案2】:

来自perldata

如果在标量上下文中计算数组,它会返回数组的长度。 (请注意,列表不是这样,它返回最后一个值,如 C 逗号运算符,也不是内置函数,它返回他们想要返回的任何内容。)

有时在标量上下文中返回数组的结果(func2func3),有时在标量上下文中返回字符串文字的结果(func1),有时在标量上下文中返回 pop 的结果(func4)。因此有区别。

【讨论】:

  • 谢谢,这可能是我错过的一点,即:列表返回最后一个值(标量),因此其行为与数组不同。
  • @Håkon Hægland,但是您没有在问题中使用任何列表?不管怎样,你想要的是this。添加到我的答案。
  • 另请注意,报价有点不准确。标量上下文中的列表不计算返回最后一个值(它会在列表上下文中返回);标量上下文中的列表返回在标量上下文中评估的列表的最后一项。 perl -E'@a=qw(x y); say @a,@a; say scalar(@a,@a)'.
猜你喜欢
  • 1970-01-01
  • 2019-05-22
  • 2022-01-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多