从函数返回perl中的+ {}或{}与返回ref或value之间的区别

时间:2017-02-07 21:37:47

标签: perl

我刚刚开始与一个新的团队新工作。他们告诉我,我们在perl模块中返回ref而不是value。我也看到像return +{foo=>'bar'}; and return {foo=>'bar'};这样的东西有什么区别?是否返回ref或value?

2 个答案:

答案 0 :(得分:17)

+中的return +{foo=>'bar'}完全没用。

首先,一些背景知识。

Perl语言含糊不清。举个例子

sub f {
   {  }     # Is this a hash constructor or a block?
}

{ }是块的有效语法(“裸循环”) { }是散列构造函数的有效语法 两者都被允许作为声明!

所以Perl必须猜测。 Perl通常猜对了,但并不总是这样。你可以给它“提示”。一元 - +可用于执行此操作。一元 - +是一个完全透明的运算符;它什么都不做。但是,必须后跟表达式(不是语句)。 { }只有一种可能的含义作为表达式。

+{ }   # Must be a hash constructor.

同样地,你可以欺骗Perl以另一种方式猜测。

{; }   # Perl looks ahead, and sees that this must be a block.

以下是Perl猜错的例子:

map { {} } 1..5   # ok. Creates 5 hashes and returns references to them.
map {}, 1..5      # XXX Perl guesses you were using "map BLOCK LIST".
map +{}, 1..5     # ok. Perl parses this as "map EXPR, LIST".

至于问题中的代码,return后面必须跟一个表达式(如果有的话),因此return { ... };只有一种可能的解释,所以+完全没用那里。

大多数人只在必要时消除歧义。其他人可能会添加+,只要它不明确(即使Perl猜对了)。但这是我第一次听说在每个哈希构造函数前使用+

答案 1 :(得分:9)

  

区别是什么?

那些是完全相同的,所以+是无关紧要的。您可以使用B::Deparse

来查看此内容
$ perl -MO=Deparse -e'sub foo { return { foo => "bar" } }'
sub foo {
    return {'foo', 'bar'};
}
-e syntax OK

$ perl -MO=Deparse -e'sub foo { return +{ foo => "bar" } }'
sub foo {
    return {'foo', 'bar'};
}
-e syntax OK

在这两种情况下,您都会返回对哈希的引用。

正如Hunter McMillen在评论中所说,在某些情况下,您需要使用一元+运算符来解决歧义。

例如,要区分匿名哈希和map中的块:

$ perl -e'@a = map { $_ => "foo" }, 1..3'   # { ... } treated as a block
syntax error at -e line 1, near "},"
Execution of -e aborted due to compilation errors.

$ perl -e'@a = map +{ $_ => "foo" }, 1..3'  # { ... } treated as a hashref
  

是否返回ref或value?

通过"返回一个值,"我假设你的同事意味着这样的事情:

sub foo {
    my %bar = ( baz => 'qux' );
    return %bar;  # as opposed to \%bar
}

my %hash = foo();

子程序只能返回标量列表,因此大致相当于

my %hash = ('baz', 'qux');

如果%bar包含许多项目,则复制此列表会变得很昂贵,因此最好返回引用:

sub foo {
    my %bar = ( baz => 'qux' );
    return \%bar;
}

my $hashref = foo();