Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

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

by choroba (Bishop)
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.

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

Replies are listed 'Best First'.
Re: Can you use string as a HASH ref while "strict refs" in use?
by LanX (Bishop) 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?
Corion had a meeting with some startup today. They have a very interesting DB proxy product, but their tech stack is really, really weird. They use the Pg wire protocol but not the Pg libraries to handle it. They support Pg SQL syntax, but don't use ...
[Corion]: ... the Pg parser (or so they claim).
[Corion]: Also, they rolled their own user management instead of supporting LDAP for user/role management, but that just shows that they're new in the enterprise market :)
Corion also just now realizes they didn't leave business cards.
[erix]: can you drop a name? :)
[karlgoethebier]: Corion: "...didn't leave business cards" Those guys came from Muränia?

How do I use this? | Other CB clients
Other Users?
Others cooling their heels in the Monastery: (13)
As of 2018-04-19 12:19 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Notices?