【问题标题】:Why does `$v = () = split` return 1?为什么`$v = () = split` 返回 1?
【发布时间】:2012-09-26 00:57:03
【问题描述】:

perldoc 说“标量上下文中的列表分配返回列表分配右侧的元素数”但是当我尝试此代码时:

perl -e '$_="aaaaa";print $v=(()=split //)'

输出是1,这让我很困惑。 (我期待的答案是5。)

谁能解释一下?

【问题讨论】:

    标签: perl


    【解决方案1】:

    根据split 文档:

    当分配给一个列表时,如果 LIMIT 被省略或为零,Perl 提供 一个 LIMIT 比列表中的变量数大一 <...>

    由于您指定了空列表,split 只返回 1 个结果,而这个结果数正是您的变量中的结尾。

    【讨论】:

    • 这是一个奇怪的极端案例。
    • @darch,完美记录,一无所有!
    【解决方案2】:

    split 具有某种疯狂的超魔力,可以让它知道它何时位于左侧有列表的作业的右侧,并根据数字调整其行为该列表中的项目。

    这在perlfunc 中被描述为“避免不必要的工作”,但您发现该优化导致的行为存在明显差异。

    要查看发生了什么的一些证据,请通过 Deparse 运行您的脚本,如下所示:

    perl -MO=Deparse -e '$_="aaaaa";print $v=(()=split //)'
    

    更新:我去寻找实现它的代码,但它不是我预期的。实际上优化是由赋值运算符 (op.c:Perl_newASSIGNOP) 执行的。 split 不太了解它的上下文。

    【讨论】:

    • 非常有帮助。我现在知道原因了。
    【解决方案3】:

    你为什么要分配一个空数组? ()=(split //) 位。这最终会导致 - 嗯,一团糟。或者,在您的情况下,一个大小为 1 的数组中包含的内容不多。

    另外,这太晦涩难懂了。 perl 以只写而闻名,所有修改 $_ 和使用它并不能帮助其他人——或者你——理解发生了什么。

    试试类似的东西

    perl -e '$v = (split //, "aaaaa"); print "$v\n"'
    

    或者,如果您希望复制测试的行为:

    perl -e '$v = () = (split //, "aaaaa"); print "$v\n"'
    

    【讨论】:

    • 我只是想测试一下perl的特性,没有实际用处。考虑以下代码: perl -e '$_="aaaaa";print $v=(()=//g)' ,它的工作原理与 perldoc 说的一样
    • 他没有分配给一个空数组,他分配给一个空列表。我永远不会让不知道区别的人审查我的代码 :-) 这个技巧被称为“goatse operator”(参见catonmat.net/blog/secret-perl-operators/#goatse),它通常非常有用。
    • 我的一个坏习惯——我也用 python 元组来做。但我非常不喜欢该页面上的许多操作员。它们增加了语言的只写性。
    • @DaveCross,让我看不到有人称此为山羊。
    【解决方案4】:

    是的,但是:

    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或列表操作返回数组引用?
    • 列表是不是数组。 (( a , a , a , a , a )) 完全等价于 ( a , a , a , a , a ) 并且有 5 个元素。
    • 好吧,我以为($x,$y,('a','a','a'))有3个元素,($x,('a','a','a','a'))有2个元素,( ('a','a','a','a','a') )只有一个。没有道理吗?
    • @Orabîg,查看p3rl.org/perldata#List-value-constructors。本节中还有关于插值的有用信息。 (而且它也恰好解释了这个问题中使用的确切 = () = 构造。)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-20
    • 1970-01-01
    • 1970-01-01
    • 2011-08-14
    • 2012-01-25
    • 2012-03-05
    • 2017-06-04
    相关资源
    最近更新 更多