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

Hi all.

I am trying to create constant hashrefs that contain other constant hashrefs. I am using subs to do this because it fits the style. What I am finding is rather odd behavior, the type changes for the 3rd constant in this snippet:
#!/usr/bin/perl use warnings; use strict; use Data::Dumper; sub make_hashref {{ foo => 'bar', }} sub make_hashref2 {{ boo => 'too', %{ make_hashref() }, }} sub make_hashref3 {{ %{ make_hashref() }, boo => 'too', }} print Dumper make_hashref(); print Dumper make_hashref2(); print Dumper make_hashref3();
The first 2 hashrefs display as expected:
$VAR1 = { 'foo' => 'bar' }; $VAR1 = { 'foo' => 'bar', 'boo' => 'too' };
But the 3rd one is no longer a reference:
$VAR1 = 'foo'; $VAR2 = 'bar'; $VAR3 = 'boo'; $VAR4 = 'too';
As far as I know, there should be no difference between 2 and 3. I find that if I explicitly `return' the hashref in example 3, it functions properly. Is there a subtlety that I am missing? Is this a bug?

This is perl, v5.6.1 built for sun4-solaris-64int

Replies are listed 'Best First'.
Re: Constant Hashref Strangeness
by simonm (Vicar) on Dec 12, 2004 at 20:54 UTC
    Curly braces can be used either to create hashes or to enclose code blocks. Perl tries to figure out which you mean and is usually right, but sometimes it guesses wrong. It's not a "bug", per se; you just need to add the return or otherwise disambiguate what it is that you want.
Re: Constant Hashref Strangeness
by Errto (Vicar) on Dec 13, 2004 at 04:53 UTC

    If you wish to force Perl to interpret a set of braces as an anonymous hash composer rather than a BLOCK in a situation where it otherwise wouldn't, you should use the unary (+) operator. So your code becomes:

    sub make_hashref3 { +{ %{ make_hashref() }, boo => 'too', }; }

    If this looks ugly to you, use return:

    sub make_hashref3 { return { %{ make_hashref() }, boo => 'too', }; }

    I added semicolons to both examples for added clarity, though they are certainly optional.

Re: Constant Hashref Strangeness
by Thilosophy (Curate) on Dec 13, 2004 at 02:01 UTC
    I am trying to create constant hashrefs that contain other constant hashrefs.

    This is probably not a problem, but you are not creating hashrefs that contain other hashrefs. You are creating hashrefs that contain a copy of the contents of other hashrefs. They are not bound to eachother in any way, later changes in one do not affect the other (but you said they are constant anyway).

    ( %{ make_hashref() } ) # makes a (shallow) COPY of the data in the hashref