hardburn has asked for the wisdom of the Perl Monks concerning the following question:

Getting right to the dirty part, here is the code:

{ my @FIELDS = qw( foo bar baz); sub set_params { { map { $_ => $_ } @FIELDS }; } } my $params = set_params; use Data::Dumper "Dumper"; print Dumper($params);

(This is a sanitized version, but I know that it demonstrates the problem. The orginal had all the CGI parameters in @FIELDS, and the value in each hash entry was the CGI param.)

I'm expecting set_params() to return a hashref. What I'm seeing is what you would get if you put a list in scalar context (the number of elements in the list--6 in the above example).

It works when set_params() is changed to:

my $params = { map { $_ => $_ } @FIELDS }; return $params;

I'm not against using the above in the code, but I am interested in why the orginal didn't work, i.e., what bit of toke.c magic did I step on this time?

$ perl -v This is perl, v5.8.2 built for i686-linux

----
: () { :|:& };:

Note: All code is untested, unless otherwise stated

Replies are listed 'Best First'.
Re: Want a Hashref. Getting a List in Scalar Context.
by Belgarion (Chaplain) on May 04, 2004 at 20:36 UTC

    If you add a return to your set_params it works correctly. For example:

    { my @FIELDS = qw( foo bar baz); sub set_params { return { map { $_ => $_ } @FIELDS }; } } my $params = set_params; use Data::Dumper "Dumper"; print Dumper($params); __OUTPUT__ $VAR1 = { 'bar' => 'bar', 'baz' => 'baz', 'foo' => 'foo' };

    Update: chip's suggestion would work as well, but I personally think using return conveys the meaning more clearly.

    Update II: Using -MO=Deparse helped me to clarify what each method did.

    I really like being able to find out exactly how Perl is trying to interpret what I wrote.

      All things being equal, it's good to avoid return; it's an extra opcode that does nothing when it's at the end of the function.

          -- Chip Salzenberg, Free-Floating Agent of Chaos

        All things being equal, it's good to use return; it's an extra opcode that does nothing when it's at the end of the function but it adds to the readability.
        All things being equal, it's good to avoid return; it's an extra opcode that does nothing when it's at the end of the function.

        On the other hand it's executed instead of the leavesub op, so its just as efficient.

        But doesn't "+" become an opcode too? If so, why not err on the side of maintainability?
Re: Want a Hashref. Getting a List in Scalar Context.
by chip (Curate) on May 04, 2004 at 20:34 UTC
    A bare curly means BLOCK, not anon hash, when it occurs at the start of a statement. So if you mean it to be a hash ref, you should prefix it with something that forces it to be an expression, like a unary "+".

        -- Chip Salzenberg, Free-Floating Agent of Chaos

Re: Want a Hashref. Getting a List in Scalar Context.
by Fletch (Bishop) on May 04, 2004 at 20:37 UTC

    It's seeing the braces as a BLOCK. If you prefix it with a + it'll force it to be interpreted as an EXPR and hence generate a hashref.

    { my @FIELDS = qw( foo bar baz); sub set_params { +{ map { $_ => $_ } @FIELDS }; } } my $params = set_params; use Data::Dumper "Dumper"; print Dumper($params);

    There's another semi-common case where this happens, but I can't recall it off hand . . .

      There's another semi-common case where this happens, but I can't recall it off hand . . .
      Sometime shift is indicated as +shift as hash key to prevent considering it as bare word 'shift' where actually the return value of function shift is intended.
Re: Want a Hashref. Getting a List in Scalar Context.
by TravelByRoad (Acolyte) on May 05, 2004 at 14:40 UTC
    Regarding the explicit vs implicit 'return' debate, it seems relevant to point out that reliance on the implicit return led hardburn (the original poster) to misunderstanding his own code.

    I believe any systematic practice that leads to more predictable code behavior should be viewed as good, and systematic use of 'return's is one of those.

    David