【发布时间】:2012-09-26 00:57:03
【问题描述】:
perldoc 说“标量上下文中的列表分配返回列表分配右侧的元素数”但是当我尝试此代码时:
perl -e '$_="aaaaa";print $v=(()=split //)'
输出是1,这让我很困惑。 (我期待的答案是5。)
谁能解释一下?
【问题讨论】:
标签: perl
perldoc 说“标量上下文中的列表分配返回列表分配右侧的元素数”但是当我尝试此代码时:
perl -e '$_="aaaaa";print $v=(()=split //)'
输出是1,这让我很困惑。 (我期待的答案是5。)
谁能解释一下?
【问题讨论】:
标签: perl
根据split 文档:
当分配给一个列表时,如果 LIMIT 被省略或为零,Perl 提供 一个 LIMIT 比列表中的变量数大一 <...>
由于您指定了空列表,split 只返回 1 个结果,而这个结果数正是您的变量中的结尾。
【讨论】:
split 具有某种疯狂的超魔力,可以让它知道它何时位于左侧有列表的作业的右侧,并根据数字调整其行为该列表中的项目。
这在perlfunc 中被描述为“避免不必要的工作”,但您发现该优化导致的行为存在明显差异。
要查看发生了什么的一些证据,请通过 Deparse 运行您的脚本,如下所示:
perl -MO=Deparse -e '$_="aaaaa";print $v=(()=split //)'
更新:我去寻找实现它的代码,但它不是我预期的。实际上优化是由赋值运算符 (op.c:Perl_newASSIGNOP) 执行的。 split 不太了解它的上下文。
【讨论】:
你为什么要分配一个空数组? ()=(split //) 位。这最终会导致 - 嗯,一团糟。或者,在您的情况下,一个大小为 1 的数组中包含的内容不多。
另外,这太晦涩难懂了。 perl 以只写而闻名,所有修改 $_ 和使用它并不能帮助其他人——或者你——理解发生了什么。
试试类似的东西
perl -e '$v = (split //, "aaaaa"); print "$v\n"'
或者,如果您希望复制测试的行为:
perl -e '$v = () = (split //, "aaaaa"); print "$v\n"'
【讨论】:
是的,但是:
perl -e '$_="aaaaa";print $v=(split //)'
给出 5,以及
perl -e '$_="aaaaa";print $v=(@x=split //)'
也许你的左值 () 正在删除额外的数组元素?
编辑:顺便说一句:
perl -e '$_="aaaaa";print $v=(($x,$y)=split //)'
返回 3,因为 $v=... 命令的右视图给出:
( $x , $y , ( a , a , a ) )
所以在您原来的情况下,()=split // 返回 ( ( a , a , a , a , a ) ) (只有一个元素)
编辑:错误的数组表示法,结果是错误的,因为我的测试用例最后一分钟改变了
【讨论】:
split或列表操作返回数组引用?
($x,$y,('a','a','a'))有3个元素,($x,('a','a','a','a'))有2个元素,( ('a','a','a','a','a') )只有一个。没有道理吗?
= () = 构造。)