perl中的返回列表会导致不同的结果

时间:2015-03-05 08:26:58

标签: perl list return

my @names =  ( (), 'my', 'name' );

sub fn1 {
    my @names =  ( 'my', 'name' );
    return ( (), @names ); #<<< this must be flatted
}

sub fn2 {
    return ( (), 'my', 'name' );
}

say length fn1();  #1
say length fn2();  #4
say length @names; #1
say length scalar ( (), 'my', 'name' ); #4


say scalar fn1(); #2
say scalar fn2(); #name
say scalar @names; #2
say scalar ( (), 'my', 'name' ); #name

# but this produce same output
say fn1();  #myname
say fn2();  #myname
say @names; #myname
say ( (), 'my', 'name' ); #myname

为什么子程序fn1变量@names没有被压扁而且返回了数组而不是list?

似乎perl返回两个列表:一个是空的,第二个是数组@names。

标量上下文中的两个元素的列表返回最后一个元素 - arrray。

标量上下文中的数组是它的长度:数字2

字符串长度&#39; 2&#39;是1,但这与fn2

不同

是否有可能在fn1中展平@names?

3 个答案:

答案 0 :(得分:5)

如果出现混淆,length不会返回数组中的元素数。它返回一个字符串的大小。

你遇到的是list vs array problem in Perl。简而言之,数组是一个像@array这样的变量。列表类似于(1,2,3,4)。 Perl在标量上下文中对它们进行评估时会出现问题。

标量上下文中的@array将返回其元素数。标量上下文中的列表与C逗号运算符类似,它返回其最后一个元素。

$ perl -wle 'sub foo { @a = ("first","second"); return @a } print scalar foo()'
2

$ perl -wle 'sub foo { return("first","second") } print scalar foo()'
second

因此,当您尝试sub foo { return("first","second") } print length foo() length在标量上下文中调用foo()时。 foo()return("first", "second")中的列表视为逗号运算符,并返回返回"second"的最后一个元素。你得到6。

$ perl -wle 'sub foo { return("first","second") } print length foo()'
6

长话短说, 不返回列表 ,返回数组。

更新:我已经弄清楚了你的困惑和自己的困惑。 ()正在做某事,它将应该是一个简单的数组转换为C逗号运算符。 return( (), @names )return( @names )不是一回事。让我们分开吧。

在标量上下文中,return( @name )表示“在标量上下文中评估此数组”并返回元素数。在列表上下文中,它将返回@names的全部内容。简单。这就是你想要使用的东西。

另一方面,

return( (), @names )逗号运算符。在列表上下文中,它将返回整个列表,该列表展平为@names。在标量上下文中,它将返回最后一个元素,即@names,然后将在标量上下文中评估它返回元素的数量。

要了解这是怎么回事,如果我们在结尾添加另一个元素就是我们得到的。

sub foo { return (), @names, 42 }
print scalar foo;    # 42

这里发生的部分原因是return不像普通功能那样。在对它们采取行动之前,它不会将其参数压缩成数组。您将返回表达式(), @names, 42的字面值,即逗号运算符。

我现在可以看到为什么你开始使用(),但你所做的只是强制表达式被评估为逗号运算符。停止使用它,这是一个拐杖,很难理解。您需要做的是learn about return contexts

我非常强大的经验法则是,不要返回列表,返回数组。

答案 1 :(得分:2)

lengthscalar强制标量上下文,而say强制列出上下文。

请注意,长度与字符串匹配:

String  Length
--------------
2        1
name     4
2        1
name     4

答案 2 :(得分:0)

我得到了答案:http://perldoc.perl.org/functions/scalar.html

如果我真的想从子程序返回数组(NOT LIST),无论调用上下文我都必须写:

return @{ [ @names ] } 

而不是

return ( (), @names );

因为在标量上下文中调用函数fn1确实意味着:

return scalar ( (), @names );

我必须查看返回运算符的说明:http://perldoc.perl.org/functions/return.html

EXPR的评估可能在列表,标量或无效上下文中,具体取决于返回值的使用方式

Schwern的更详细描述:

在标量上下文中,return( @name )表示&#34;在标量上下文中评估此数组&#34;并返回元素数量。在列表上下文中,它将返回所有@names。简单。这就是你想要使用的东西。

另一方面,

return( (), @names )逗号运算符。在列表上下文中,它将返回整个列表,该列表变平为@names。在标量上下文中,它将返回最后一个元素,即@names,然后将在标量上下文中返回它返回元素数量。

要了解这是怎么回事,如果我们在最后添加另一个元素,那就是我们得到的东西。

sub foo { return (), @names, 42 }
print scalar foo;    # 42