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

问题描述 投票:0回答:2

我刚刚开始在新的团队、新的地方工作。他们告诉我我们在 Perl 模块中返回 ref 而不是 value。我还看到类似

return +{foo=>'bar'}; and return {foo=>'bar'};
有什么区别?以及是否返回ref或value?

perl
2个回答
29
投票

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


首先,一些背景知识。

Perl 语言有歧义。举个例子吧

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

{ }
是块的有效语法(“裸循环”)。
{ }
是哈希构造函数的有效语法。
两者都可以作为声明!

所以 Perl 必须猜测。 Perl 通常会猜测正确,但并非总是如此。你可以给它“提示”。 Unary-

+
可以用来做到这一点。 Unary-
+
是一个完全透明的运算符;它什么也不做。[1] 但是,它后面必须跟一个表达式(而不是语句)。
{ }
作为表达式只有一种可能的含义。

+{ }   # 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. Unary-
    +
    甚至不强加标量上下文。相反,它将其上下文传播到其操作数上。

11
投票

有什么区别?

这些是完全相同的,所以

+
是无关的。您可以使用 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();
© www.soinside.com 2019 - 2024. All rights reserved.