Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

Ovid (2709)

Ovid
  (email not shown publicly)
http://publius-ovidius.livejournal.com/
AOL IM: ovidperl (Add Buddy, Send Message)

Stuff with the Perl Foundation. A couple of patches in the Perl core. A few CPAN modules. That about sums it up.

Journal of Ovid (2709)

Monday July 31, 2006
07:43 AM

Hash interpolation failure in string

[ #30484 ]

So a coworker wanted to know the syntax for getting hash interpolation to work. He had something similar to this:

print "value is $data{'value'}\n";

I assured him that would be fine but he said that he's been bitten by this before, even when using interpolated strings. So just to be sure, I wrote up a simple test. One test line fails. Without running that, can you guess which one and why?

#!/usr/bin/perl

use strict;
use warnings;
use Test::More tests => 6;

my %french_for = (
    one => 'un',
);

my $num = 'one';
is "$french_for{one}",      'un', 'bare literal key';
is "$french_for{'one'}",    'un', 'single quoted literal key';
is qq[$french_for{"one"}],  'un', 'double quoted literal key';
is "$french_for{$num}",     'un', 'bare variable key';
is "$french_for{'$num'}",   'un', 'single quoted variable key';
is qq[$french_for{"$num"}], 'un', 'double quoted variable key';

To be fair, I guess the failure isn't too surprising but in reading through perltrap, it doesn't appear to be documented. Is it documented and I just missed it?

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.
  • Surely:

    is "$french_for{'$num'}", 'un', 'single quoted variable key';

    Will fail. You've single quoted '$num' hence you're looking for the key "\$num".
    • Yes, that's the failure, but I don't know why that should be obvious because if you add diag "'$num'" to the end of that script, you get this:

      # 'one'

      In other words, a variable in single quotes will interpolate if it's embedded in a double quoted string but not used as the key to a hash or an index into an array. That seems a bit odd and it would be nice if it were documented better. I should submit a patch for perltrap if it's not documented.

      • I tend to consider hash interpolation as being outside of the string, even though it's embedded. I consider there to be an invisible ". and ." around it.
      • a variable in single quotes will interpolate if it's embedded in a double quoted string but not used as the key to a hash or an index into an array. That seems a bit odd

        Actually what seemed odd to me was that the first example (with single quotes around the literal) worked OK. But given that, I did expect it to fail round a variable (as in I guessed what the failure would be before even seeing your list of choices).

        Yes directly in a double-quoted string literal single quotes don't prevent a variable be

        • Well, basically the stuff after a $ or @ sigil gets treated sort of like it's code to be executed. This leads to the following:

            temp $ touch foo.bar
            temp $ ls
            foo.bar
            temp $ perl -e 'print "$ENV{`rm foo.bar`}"'
            temp $ ls
            temp $

          I know you and I have discussed this bit, but others might want to be aware of it.

  • I certainly wasn't aware of that behavior. I would have expected the double quotes to cause everything inside to be interpolated, presumably starting with the innermost thing ($num in this case).