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
Run Code Online (Sandbox Code Playgroud)
为什么在子程序fn1变量@names没有被压扁而返回数组而不是list?
似乎perl返回两个列表:一个是空的,第二个是数组@names.
标量上下文中的两个元素的列表返回最后一个元素 - arrray.
标量上下文中的数组是它的长度:数字2
字符串'2'的长度为1,但这与fn2不同
是否有可能在fn1中展平@names?
如果有混淆,length则不返回数组中的元素数.它返回一个字符串的大小.
您遇到的是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
Run Code Online (Sandbox Code Playgroud)
因此,当您尝试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
Run Code Online (Sandbox Code Playgroud)
长话短说,不要返回列表,返回数组.
更新:我已经弄清楚你的困惑和我自己的困惑. ()正在做某事,它将应该是一个简单的数组转换为C逗号运算符. return( (), @names )并且return( @names )是不一样的东西.让我们分开吧.
在标量上下文中,return( @name )" 在标量上下文中计算此数组 "并返回元素的数量.在列表上下文中,它将返回所有@names.简单.这是你想要使用的.
return( (), @names )另一方面是逗号运算符.在列表上下文中,它将返回整个列表,它会变平@names.在标量上下文中,它将返回最后一个元素,@names然后在标量上下文中返回该元素,返回其元素数量.
要了解这是真的,如果我们在结尾处添加另一个元素,那就是我们得到的.
sub foo { return (), @names, 42 }
print scalar foo; # 42
Run Code Online (Sandbox Code Playgroud)
这里发生的部分原因return不是正常功能.在对它们采取行动之前,它不会将其参数压缩成数组.您将返回表达式的字面值,该表达式(), @names, 42是逗号运算符.
我现在可以看到你开始使用的原因(),但你所做的只是强制表达式被评估为逗号运算符.停止使用它,这是一个拐杖,很难理解.你需要做的是学习返回上下文.
我非常强大的经验法则仍然是,不返回列表,返回数组.