Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

Using eval to create a hash

by davidfilmer (Sexton)
on Jun 01, 2015 at 01:49 UTC ( [id://1128517]=perlquestion: print w/replies, xml ) Need Help??

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

Greetings, Masters. I'm reading a long list of key/value pairs from a file, and I want to populate that into a hash. For demonstration, kindly consider this sample code:
use Data::Dumper; my %index1 = ( 1 => 'foo', 2 => 'bar', 3 => 'baz', ); print Dumper \%index1; #looks as expected my $index = q{ 1 => 'foo', 2 => 'bar', 3 => 'baz', }; print Dumper $index; #looks as expected my %index2; eval{ %index2 = ( $index ) }; print Dumper \%index2; #hash has one key ($index) and value undef __END__
To my unenlightened eyes, my eval for %index2 is functionally and syntactically equivalent to the creation of %index1. I humbly approach the Oracles for wisdom.

Replies are listed 'Best First'.
Re: Using eval to create a hash
by AnomalousMonk (Archbishop) on Jun 01, 2015 at 02:14 UTC

    The statements
        my %index2;
        eval{ %index2 = ( $index ) };
    are equivalent to the statement
        my %index2 = ( $index );
    with the only difference being the time at which they are evaluated: the eval statement is evaluated at run time; the other statement is evaluated at compile time | the eval statement is executed such that run-time errors are captured; both statements must be syntactically correct at compile time. (Thanks to Anonymonk for pointing out below the original confusion of this statement. As always, see The Docs for full details!)

    But consider
        my %index2 = ( $index );
    This statement attempts to initialize a hash with the single string  $index used as a key (and with no associated value) and not with a key/value pair. That's not going to work. Instead, consider

    c:\@Work\Perl\monks>perl -wMstrict -MData::Dumper -le "my $index = q{1 => 'foo', 2 => 'bar', 3 => 'baz'}; my %hash = ( $index => 'foobar' ); print Dumper \%hash; " $VAR1 = { '1 => \'foo\', 2 => \'bar\', 3 => \'baz\'' => 'foobar' };
    Here, it's possible to see that the entire string of  $index becomes the key for the value 'foobar'.

    Doing a full string eval would have given you the result you expected:

    c:\@Work\Perl\monks>perl -wMstrict -MData::Dumper -le "my $index = q{1 => 'foo', 2 => 'bar', 3 => 'baz'}; my %hash; eval qq{ %hash = ($index); }; print Dumper \%hash; " $VAR1 = { '1' => 'foo', '3' => 'baz', '2' => 'bar' };
    or maybe just
    c:\@Work\Perl\monks>perl -wMstrict -MData::Dumper -le "my $index = q{1 => 'foo', 2 => 'bar', 3 => 'baz'}; my %hash = eval qq{ ($index) }; print Dumper \%hash; " $VAR1 = { '1' => 'foo', '3' => 'baz', '2' => 'bar' };
    Update: Or indeed just  my %hash = eval $index; as LanX points out below!

    See eval for a discussion of the differences between the
        eval { statement; ...; };
    and
        eval "statement; ...;";
    forms (referred to respectively as  eval BLOCK and  eval EXPR in the doc).


    Give a man a fish:  <%-(-(-(-<

      the eval statement is evaluated at run time; the other statement is evaluated at compile time.

      I don't think that's accurate for the eval BLOCK form... perhaps you're thinking of evaling a string? Also it depends on what you mean by "evaluated" (compiled vs. executed).

Re: Using eval to create a hash
by LanX (Saint) on Jun 01, 2015 at 08:07 UTC
    You a are using block eval not string eval.

    Try %index = eval "$index"

    ( actually the double quotes are even not necessary here )

    Cheers Rolf
    (addicted to the Perl Programming Language and ☆☆☆☆ :)
    Je suis Charlie!

Re: Using eval to create a hash
by Discipulus (Canon) on Jun 01, 2015 at 07:56 UTC
    Yes you can, when you understand it well, eval is a powerfull tool. Read carefully the AnomalousMonk's reply to get rid of the error in your original code: if you have doubts on plain code it will be a pain to debug string evaluated code.

    I used eval string form, with no pudor and gaining a lot of critics, in my experiment cpan's namespace navigator.
    In my code there is a big evaluation part that transforms data from a text file into a big, big hash.

    This is what i remember about my troubles doing that: as usual 'bad data ruins your day', so you need to be sure about what you are evaluating. If you split on withespaces and take the first result as the key you can be bitten by a unexpected strings that can cause code to run outside your intention, or strings that break your data structure.

    If you expect a keypair for each line of your file, check for the total count of your keys is equal to line number at the end of file. The field used as key must follow rules for keys names in Perl. If you need to tranform something before using as keys(special chars, withespaces..) you need tobe able to do the two way conversion safely and reliably...
    Duplicates are normal in text files but not in hash's key: it will results into an update of such keys on succesive reads of the same string..

    Take a look also to Data::Diver module that creates datastructures from strings.

    HtH
    L*
    There are no rules, there are no thumbs..
    Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
Re: Using eval to create a hash
by BillKSmith (Monsignor) on Jun 01, 2015 at 12:38 UTC
    Perhaps this is what you mean:
    use strict; use warnings; use Data::Dumper; my $index = q{ 1 => 'foo', 2 => 'bar', 3 => 'baz', }; my %index3 = eval $index; print Dumper \%index3;
    OUTPUT:
    $VAR1 = { '1' => 'foo', '3' => 'baz', '2' => 'bar' };
    Bill
Re: Using eval to create a hash
by Anonymous Monk on Jun 01, 2015 at 02:27 UTC

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others exploiting the Monastery: (5)
As of 2024-04-19 11:34 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found