Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much
 
PerlMonks  

Can you use string as a HASH ref while "strict refs" in use?

by choroba (Abbot)
on Dec 06, 2013 at 00:04 UTC ( #1065867=perlmeditation: print w/ replies, xml ) Need Help??

At work, I was given a code to add functionality. You can probably imagine - a CGI script that shows a list, some of whose elements might be selected. The part responsible for handling the selected elements confused me (simplified):
for my $id (@selected) { $list{$id}{selected} = 1; } for my $key (keys %list) { print qq(<li name="$key"); print ' class="selected"' if $list{$key}{selected}; print ">$list{$key}\n"; }

Wait, what's going on? We test for $list{$key}{selected}, so $list{$key} is a hash reference. Then, we print $list{$key} - but in the output, we do not get any HASH(0x2561a68), but the correct goods' names. I asked a coworker, and she told me this part of the script was "dark magic"; she had debugged it once and still remembered the value was coming out even if it should not. I played a bit with the script to remember I have already seen a similar behaviour: of course, the script does not use strict! Try yourself:

#!/usr/bin/perl # Script part 1. use warnings; use strict; my $code = << '__CODE__'; %list = ( scalar => 'Plain', ref => 'Overwritten' ); $list{ref}{selected} = 1; for my $key (keys %list) { print "$key: $list{$key}"; print " - Selected" if $list{$key}{selected}; print "\n"; } __CODE__ { no strict; my %list; eval $code; print "Wow: $Overwritten{selected}\n"; }

The last print explains what happens: Perl sees you are trying to use $list{ref} as a hash reference, while its value is the string "Overwritten". It therefore creates a hash of that name for you (even more funny if the string contains spaces).

So far, so good. Lesson learnt: the people who tell you "use strict" know what they say. I tried to explain to the coworkers what the problem was, but those not familiar with Perl were not able to understand.

But then, I thought to myself: Is it possible to make the code work even under strict? tie and overload would probably be useful, as I remembered from Programming Perl. And after several minutes, I was able to run the code under strict. You can test your skills before revealing my solution:

Just for completness, this is the "common" behaviour I expected at the beginning:

# Script part 3. { my %list; eval "$code;1" or die $@; }

Note: The three last code examples should be kept in one file.

لսႽ ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ

Comment on Can you use string as a HASH ref while "strict refs" in use?
Select or Download Code
Re: Can you use string as a HASH ref while "strict refs" in use?
by LanX (Canon) on Dec 06, 2013 at 01:12 UTC
    I'm not sure if I got it ...

    ... you mean that w/o strict auto-vivification automatically creates new hash-variables in the current package (here %string_not_ref}, correct?

    DB<100> $hash{hunger}="string_not_ref" => "string_not_ref" DB<101> $hash{hunger}{games}="movie" => "movie" DB<102> \%string_not_ref => { games => "movie" } DB<103> use strict; $main::hash{hunger}{games}="movie" Can't use string ("string_not_ref") as a HASH ref while "strict refs" +in use at (eval 26)[multi_perl5db.pl:644] line 2.

    Maybe show this to your colleagues and ask them if they really intended to magically create new random variables at top-level. =)

    Cheers Rolf

    ( addicted to the Perl Programming Language)

Re: Can you use string as a HASH ref while "strict refs" in use?
by Anonymous Monk on Dec 06, 2013 at 03:26 UTC

    Can you use string as a HASH ref while "strict refs" in use?

    Of course you can , just use it as a key of a hash whose value is a hashref, naturally:D

    my %pad; $pad{$string} ||= {}; $pad{$string}{hashref}=12; my $global = \%global::; $global->{$string}{hashref}=12;

    I tried to explain to the coworkers what the problem was, but those not familiar with Perl were not able to understand.

    Did you compare a "symbolic reference" to a "symbolic link"?

    Yes, its hard to understand one part of a machine without understanding how all the parts work

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlmeditation [id://1065867]
Approved by boftx
Front-paged by Arunbear
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others scrutinizing the Monastery: (7)
As of 2014-09-17 22:50 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    How do you remember the number of days in each month?











    Results (100 votes), past polls