【问题标题】:Question about precedence + repetition modifer关于优先级+重复修饰符的问题
【发布时间】:2011-06-30 15:25:55
【问题描述】:

请您向我解释一下这种显然不一致的行为:

use strict;
my @a;

print "a" x 2; # this prints: aa
@a = "a" x 2; print @a; # this prints: aa

print ("a") x 2; # this prints: a
@a = ("a") x 2; print @a; # this prints: aa

最后一个不应该打印一个'a'吗?

编辑:好的,现在这对我来说更有意义: “二进制“x”是重复运算符...在列表上下文中,如果左操作数被括号括起来或者是由 qw/STRING/ 组成的列表,它会重复该列表。” perlop

这对我来说一清二楚(二进制 x - 为什么使用二进制这个词?有否定的 X 吗?) 但无论如何: @a = ("a") x 2 # 似乎在列表上下文中,因为我们在开头有一个数组 - 数组不是列表,但它包含一个列表,所以我认为我们可能有一个列表上下文,(不是数组上下文,尽管它们可能是同义词)。

我想“左操作数”是(“a”)。 (要么是那个,要么是@a)。 perlop 没有说明操作数实际上是什么,查询 perldoc.perl.org 给出“未找到匹配项”,而谷歌搜索给出“在计算机编程中,操作数是用于描述任何能够被操纵的对象的术语。”比如数组。

所以左操作数可能被括在括号中,所以它可能应该“重复列表”。该列表是:("a") x 2 或者是:("a")

如果我们重复("a") x 2,我们将得到("a") x 2 ("a") x 2。这似乎不对。

如果我们输入:print $a[1],我们将得到一个 'a',因此“它重复列表”意味着 Perl 将 ("a") x 2 转换为 ("a", "a"),因此我们有效地得到了 @a=("a", "a")

但是,print ("a") x 2 不会变成 ("a", "a")。那是因为 print 是一个具有高优先级的“列表运算符”。所以我们有效地得到:(print ("a")) x 2

数组是一个术语,所以它也有很高的优先级,但是@a=stuff 涉及到赋值运算符=,它的优先级相对较低。所以它与印刷品完全不同。

【问题讨论】:

  • 有些字母,你只是不应该这样连续交替。
  • 我不明白你的意思
  • @DanD 伙计,我一直很乐意回答你的其他问题,因为你提出的问题很好,我和其他人会继续回答你。然而,也许是时候喝上一杯好酒,然后在命令行中使用 perldocs(perldoc.perl.org 或 perldoc)。brian d foy 有一篇关于 perlmonks 的精彩帖子,他称之为“文档文档”,我在我的个人资料中链接到:perlmonks.org/?node_id=408254
  • @DanD 伙计,我并不是要劝阻你,重读我上面的内容似乎可能采取了错误的方式。实际上,我的意思是您似乎很喜欢这些错综复杂的内容,并且文档对于像我这样的人(他们会提出类似的问题)非常有趣。当你发现一些奇怪的东西时,请继续在这里询问。我已经问了几个stackoverflow.com/questions/4865447/demystifying-the-perl-glob,尤其是这个stackoverflow.com/questions/4045467/…,如果在修复过程中没有发现它,我会算作在perl 中找到了我的第一个错误。
  • 几个月前,我和本地、我们和我的人相处得很艰难。查看 perldoc 和谷歌搜索并没有真正帮助,最后我只是放弃了。但是,我现在在这里问了3个问题,每次都向我解释,加深了我的理解。所以,我现在觉得我可以回去挖掘关于我当地和我们的问题,我会得到量身定制的回复和解释。现在阅读 perldoc 似乎也更有可能——即使某些代码非常简洁且难以理解,我也可以在这里提问。

标签: perl operator-precedence


【解决方案1】:

在你的脚本中添加use warnings;,然后你会得到warnings like

print (...) interpreted as function .
Useless use of repeat (x) in void context .

print (("a") x 2); 那样做# 打印:aa

正如您在 cmets 中提到的,如何格式化您的代码,我会说请参阅 Perltidy

Perltidy 是一个 Perl 脚本,它缩进并重新格式化 Perl 脚本以使其更易于阅读。如果您编写 Perl 脚本,或花大量时间阅读它们,您可能会发现它很有用。

更多关于Perltidy的信息:

您可以下载perltidy并运行它 使用其默认值,或自定义它以使用您喜欢的支撑样式、缩进宽度等。

定制很容易,并且有大量的选项。默认值通常是一个很好的起点。

Perltidy 也可用于生成代码的彩色 HTML 输出

Perltidy 带有一组合理的默认值;但它们可能不适合您。幸运的是,您可以使用 tidyview 作为图形用户界面来预览 perltidy 对您的代码所做的更改,并查看哪些选项最适合您。您可以从 CPAN 下载tidyview

注意:始终在脚本开头添加use strictuse warnings

【讨论】:

  • 好吧,我应该试试。谢谢。而且,我的意思是当我发布我的问题时,它都是黑色字体,然后有人(或某物)来到这里并将其更改为不同的颜色。我只是想知道这样的事情怎么可能。 print+("a")x2 我从来没想过那个...
  • 参见editing help page,您将获得关于,Markdown 将纯文本格式转换为花哨的 HTML 格式的信息。
【解决方案2】:

我认为您出现奇怪行为的原因是因为 perl 的 print 命令需要一个列表。引用自relevant documentation

还要注意不要在 print 关键字后面加上左括号,除非您希望相应的右括号终止 print 的参数;在所有参数周围加上括号。

加上括号使它像一个函数一样工作。考虑是否执行此测试用例:

x("y") x 2;

sub x {
    my $y = shift;
    print "1: $y\n"; #result 1: y
    my $y = shift;
    print "2: $y\n"; #result 2:
}

当编写为函数调用时,您的结果对于被评估为其参数的函数而不是在以下操作之后被评估的赋值是一致的。

【讨论】:

    【解决方案3】:

    你被一个常见的 Perl 解析陷阱所困扰。您的第三条语句print ("a") x 2 被解析为:

    (print ("a")) x 2;
    

    您可以添加另一组括号来修复解析:

    print (("a") x 2);  # prints aa
    

    【讨论】:

    • 我明白了。为什么第 4 行没有以相同的方式完成,即为什么 @a = ("a") x 2; 不被解析为 (@a = ("a")) x 2;(也请您解释一下如何正确格式化代码)
    • @DanD man - 由于运算符优先级,无法按照您所写的方式解析第 4 行(请参阅表中的 perlop)。
    • @DanD,Perl 中有一条规则“如果它看起来像函数调用,那就是函数调用”。也就是说,当您有一个函数名后跟可选的空格和一个左括号时,相应的右括号会终止该函数的参数。这记录在perlop
    • 所有答案都很有用,但我要在你的前面打一个大大的绿色勾,因为你说“常见的 Perl 解析陷阱”,这让我觉得我不是唯一一个犯错误的人.
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-20
    • 2022-11-16
    • 2011-10-19
    • 1970-01-01
    • 1970-01-01
    • 2013-12-28
    • 1970-01-01
    相关资源
    最近更新 更多