Difference between returning +{} or {} in perl from a function, and return ref or value

The + in return +{foo=>'bar'} is completely useless.


First, some background.

The Perl language has ambiguities. Take for example

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

{ } is valid syntax for a block ("bare loop").
{ } is valid syntax for a hash constructor.
And both are allowed as a statement!

So Perl has to guess. Perl usually guesses correctly, but not always. You can give it "hints". Unary-+ can be used to do this. Unary-+ is a completely transparent operator; it does nothing at all. However, it must be followed by an expression (not a statement). { } has only one possible meaning as an expression.

+{ }   # Must be a hash constructor.

Similarly, you can trick Perl to guess the other way.

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

Here's an example where Perl guesses wrong:

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".

As for the code in the question, return must be followed by an expression (if anything), so there's only one possible interpretation for return { ... };, so the + is completely useless there.

Most people only disambiguate when necessary. Others might add + whenever it's ambiguous (even if Perl would guess right). But this is the first time I've heard of using + in front of every hash constructor.


Whats the difference?

Those are exactly the same, so the + is extraneous. You can see this by using 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

In both cases, you're returning a reference to a hash.


As Hunter McMillen said in a comment, there are some cases where you need to use the unary + operator to resolve ambiguity.

For example, to distinguish between an anonymous hash and a block in a 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

And whether to return ref or value?

By "returning a value," I assume your coworkers mean something like this:

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

my %hash = foo();

Subroutines can only return a list of scalars, so this is roughly equivalent to

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

If %bar contains many items, copying this list becomes expensive, so it can be better to return a reference instead:

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

my $hashref = foo();

Tags:

Perl