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

前端 未结 2 641
渐次进展
渐次进展 2020-12-16 18:32

I just started work with a new team new place. They told me we return ref instead of value in our perl modules. Also I saw something like return +{foo=>\'bar\'}; an

相关标签:
2条回答
  • 2020-12-16 18:59

    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();
    
    0 讨论(0)
  • 2020-12-16 19:13

    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.

    0 讨论(0)
提交回复
热议问题