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