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?
答案 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)
答案 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