【问题标题】:Parenthesis in a perl function callperl 函数调用中的括号
【发布时间】:2013-12-08 19:28:51
【问题描述】:

AFAIK,perl 中的括号用于:

  • 在表达式中设置计算优先级
  • 列出清单

所以,

my $r = ($x+$y) * $z;
my(@l) = (1,2,3);

函数调用中括号的含义是什么?我没有找到,sub 会得到一个简单的参数列表。

#!/usr/bin/env perl

use Modern::Perl;
use Data::Dumper;

sub xxx { say Dumper \@_ }

xxx( 1,  2, 3  );
xxx( 1, (2, 3) );
xxx  1, (2, 3)  ;
xxx  1,  2, 3;

对吗?

询问是因为 perl -MO=Deparse 没有从函数调用中删除括号。

所以下一个短脚本

use Moose;
has 'arg' => (is=>'rw', isa=>'Str');

返回

has('arg', ('is', 'rw', 'isa', 'Str'));

而不是简单的

has('arg', 'is', 'rw', 'isa', 'Str');

这里有什么不同吗?

【问题讨论】:

  • 只是一个评论:玩括号时,使用Deparse,-p

标签: perl


【解决方案1】:

在您的示例中,“它们都一样”的例外情况如下:

xxx (1,2), 3;

以下的区别:

has('arg', ('is', 'rw', 'isa', 'Str'));
has('arg', 'is', 'rw', 'isa', 'Str');

是前者构建一个列表,然后构建第二个列表,将第一个列表推到它上面。后者将所有内容构建为一个列表。您可以使用 B::Concise 看到差异;它们编译为略有不同的操作树。前一个示例的运行速度会稍微慢一些,但差别不大。

use strict;
use warnings;
use Benchmark qw(cmpthese);

cmpthese(-5, {
  once   => q[  my @x = (foo => (bar => 1, baz => 2))  ],
  twice  => q[  my @x = (foo =>  bar => 1, baz => 2 )  ],
});

__END__
       Rate twice  once
twice 216835/s    --   -1%
once  218228/s    1%    --

【讨论】:

  • 那个基准可能没有意义。差异是如此之小,以至于它可能只是统计波动。当然,没有看到原始数据集就无法知道。另一方面,我所期望的会略有放缓。
  • 我已经多次运行该基准测试,once 始终更快,尽管速度从未超过 1%。 (通常小于 0.5% 的差异。)
【解决方案2】:

当parens没有被deparsing删除时,这是因为它们可以用来确定优先级。 sn-ps has('arg', 'is', 'rw', 'isa', 'Str')has('arg', ('is', 'rw', 'isa', 'Str')) 产生不同的操作码(尽管在这种情况下可以安全地消除差异)。

Parens 不会创建列表。 Perl 中的“列表”不是不同的数据结构。它们只是对堆栈段的更易于理解的描述。如果有任何东西会创建一个列表,那么它将是列表上下文中的逗号运算符,。 (但它没有,因为没有列表)。

如果您正在调用的子例程在解析时已知,则来自函数调用的括号是可选的,即语法为 any_function(@args)known_function @args。已知函数也可以使用 prototypes 来更改参数的解析方式(无论是否使用了括号)。对于已知函数,解析后的调用是否使用括号无关紧要:两者都产生相同的操作码。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-27
    • 2013-04-15
    • 1970-01-01
    • 2016-06-27
    • 2011-09-29
    • 1970-01-01
    相关资源
    最近更新 更多