Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

Not So Complex Hash Question

by NateTut (Deacon)
on Jul 01, 2009 at 19:14 UTC ( #776546=perlquestion: print w/ replies, xml ) Need Help??
NateTut has asked for the wisdom of the Perl Monks concerning the following question:

In the code below I would like the Hash filled in the subroutine FillHashOne() to be accessible as a reference in $Hash. However all I get is an empty hash ref.

I think I am missing the section of my brain that is needed to understand references. I have read all the tutorials and have used references many times, but then I run into a situation like this that stymies me.

All help and suggestions are appreciated!

Update: Duh! I messed up my closure and had it inside the subroutine. It works when I fixed that.

#!/usr/bin/perl use strict; use warnings; use constant false => 0; use constant true => 1; $| = true; use Data::Dumper; my $Hash = {}; sub FillHashOne { my %HashOne; { my ($Key, $Value) = @_; if(!defined($Key)) { return(\%HashOne); } else { $HashOne{$Key} = $Value; } } } $Data::Dumper::Indent = 3; $Data::Dumper::Purity = true; $Data::Dumper::Varname = 'Hash'; $Data::Dumper::Quotekeys = true; $Hash->{'One'} = 1; $Hash->{'Two'} = 2; $Hash->{'Three'} = 3; $Hash->{'String'} = 'Foo Bar'; print __LINE__ . ":Main:\$Hash:\n" . Dumper($Hash); for (my $i = 0; $i < 10; $i++) { FillHashOne($i, "Value:\[$i\]"); } $Hash->{'HashOne'} = FillHashOne(undef()); print __LINE__ . ":Main:\$Hash:\n" . Dumper($Hash);


Updated Code:

#!/usr/bin/perl use strict; use warnings; use constant false => 0; use constant true => 1; $| = true; use Data::Dumper; my $Hash = {}; { my %HashOne; sub FillHashOne { my ($Key, $Value) = @_; if(!defined($Key)) { return(\%HashOne); } else { $HashOne{$Key} = $Value; } } } $Data::Dumper::Indent = 3; $Data::Dumper::Purity = true; $Data::Dumper::Varname = 'Hash'; $Data::Dumper::Quotekeys = true; $Hash->{'One'} = 1; $Hash->{'Two'} = 2; $Hash->{'Three'} = 3; $Hash->{'String'} = 'Foo Bar'; print __LINE__ . ":Main:\$Hash:\n" . Dumper($Hash); for (my $i = 0; $i < 10; $i++) { FillHashOne($i, "Value:\[$i\]"); } $Hash->{'HashOne'} = FillHashOne(undef()); print __LINE__ . ":Main:\$Hash:\n" . Dumper($Hash);

Comment on Not So Complex Hash Question
Select or Download Code
Re: Not So Complex Hash Question
by davorg (Chancellor) on Jul 01, 2009 at 19:47 UTC

    Your code has a number of interesting quirks, but the main problem is caused by the fact that %HashOne is defined as a lexical variable within the FillHashOne() subroutine. This means that a new, empty, version of the variable is created each time you enter the subroutine and destroyed each time you leave the subroutine.

    This is why state variables were introduced in Perl 5.10. Your code works as you want it to if you rewrite it like this:

    #!/usr/bin/perl use feature ':5.10'; use strict; use warnings; use constant false => 0; use constant true => 1; $| = true; use Data::Dumper; my $Hash = {}; sub FillHashOne { state %HashOne; { my ($Key, $Value) = @_; if(!defined($Key)) { return(\%HashOne); } else { $HashOne{$Key} = $Value; } } } $Data::Dumper::Indent = 3; $Data::Dumper::Purity = true; $Data::Dumper::Varname = 'Hash'; $Data::Dumper::Quotekeys = true; $Hash->{'One'} = 1; $Hash->{'Two'} = 2; $Hash->{'Three'} = 3; $Hash->{'String'} = 'Foo Bar'; print __LINE__ . ":Main:\$Hash:\n" . Dumper($Hash); for (my $i = 0; $i < 10; $i++) { FillHashOne($i, "Value:\[$i\]"); } $Hash->{'HashOne'} = FillHashOne(undef()); print __LINE__ . ":Main:\$Hash:\n" . Dumper($Hash);

    For it to work in earlier versions of Perl, you need to move the definition of %HashOne out of the subroutine. It's probably a good idea to keep both the variable definition and the subroutine in the same naked block. Keeping your idiosyncratic indentation style, it would look like this:

    #!/usr/bin/perl use strict; use warnings; use constant false => 0; use constant true => 1; $| = true; use Data::Dumper; my $Hash = {}; { my %HashOne; sub FillHashOne { my ($Key, $Value) = @_; if(!defined($Key)) { return(\%HashOne); } else { $HashOne{$Key} = $Value; } } } $Data::Dumper::Indent = 3; $Data::Dumper::Purity = true; $Data::Dumper::Varname = 'Hash'; $Data::Dumper::Quotekeys = true; $Hash->{'One'} = 1; $Hash->{'Two'} = 2; $Hash->{'Three'} = 3; $Hash->{'String'} = 'Foo Bar'; print __LINE__ . ":Main:\$Hash:\n" . Dumper($Hash); for (my $i = 0; $i < 10; $i++) { FillHashOne($i, "Value:\[$i\]"); } $Hash->{'HashOne'} = FillHashOne(undef()); print __LINE__ . ":Main:\$Hash:\n" . Dumper($Hash);
    --

    See the Copyright notice on my home node.

    Perl training courses

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://776546]
Approved by GrandFather
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (5)
As of 2014-10-31 05:42 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    For retirement, I am banking on:










    Results (214 votes), past polls