cLive ;-) has asked for the wisdom of the Perl Monks concerning the following question:

hi all

I know this doesn't work:

#!/usr/bin/perl use strict; use warnings; use Data::Dumper; my $var = {'one','two','red','blue'}->{'fish'}; print Dumper($var); # wanting this # $var->{'one'}->{'fish'} # $var->{'two'}->{'fish'} # etc

But why does Dumper output undef instead of an error?

And does anyone have a succinct way of doing what I'd like it to do? The example above is simplified to show weird issue. In real life, fish is a hashref, eg:

my $mime = { 'Web Page' => { icon => 'webdoc.png', ext => ['htm','html','shtml'], }, 'PHP Web Page' => { icon => 'webdoc.png', ext => ['php'], }, 'Perl' => { icon => 'script.png', ext => ['cgi','pm','pl'], }, };

What I really want is to grab the ext values and use them as keys, moving the description to the hashref value hashref.

But the above is easier to read, even if it doesn't help me find attr for files based on extension.

Or should I just forget and use the above to create a new hashref with everything in the right order on script run?

Hmmm mumble mumble

cLive ;-)

--

Replies are listed 'Best First'.
Re: strict and warnings but no error?
by blokhead (Monsignor) on May 28, 2003 at 02:12 UTC
    I'm not sure exactly what you want Data::Dumper to output here.. Look at what you've written:
    my $var = {'one', 'two', 'red', 'blue'}->{'fish'};
    Another way of writing it:
    my %hash = (one => 'two', red => 'blue'); my $hash_ref = \%hash; my $var = $hash_ref->{fish};
    Since the anonymous hash doesn't have a key named fish, you get undef when using fish as a hash subscript. I'm having trouble seeing the parallel between the example hash and the "real world" hash you present...

    Do you want to search the hash based on some inner structure? You can only fetch things based on the key, not what's in the value, as that's what hashes are for. You'll have to make some sort of reverse-lookup hash to fetch things by the ext array.

    Update: I get it now, but I still don't think the code you had should raise an error. It's a hash dereference of a valid hash.

    blokhead

Re: strict and warnings but no error?
by japhy (Canon) on May 28, 2003 at 02:18 UTC
    Hrm. If you want to have Perl restructure your hash, I'd do it in the following way:
    sub make_ext_hash { my $mime = shift; my %ext = (); for my $name (keys %$mime) { my $desc = $mime->{$name}; $ext{$_} = { icon => $mime->{$name}{icon}, name => $name, } for @{ $desc->{ext} }; } return \%ext; }
    That seems pretty straight-forward to me.

    Update, as per the cb:

    sub make_ext_hash { my $mime = shift; my %ext = (); for my $name (keys %$mime) { my %hr = ( icon => $mime->{$name}{icon}, name => $name, ); $ext{$_} = \%hr for @{ $mime->{$name}{ext} }; } return \%ext; }

    _____________________________________________________
    Jeff[japhy]Pinyan: Perl, regex, and perl hacker, who'd like a job (NYC-area)
    s++=END;++y(;-P)}y js++=;shajsj<++y(p-q)}?print:??;

Re: strict and warnings but no error?
by Zaxo (Archbishop) on May 28, 2003 at 02:15 UTC

    In line 5 you attempt to (wrongly) dereference $var before the end of the statement, but you wind up dereferencing an anonymous hash (with keys 'one' and 'red') by a key ,'fish', that doesn't exist, giving $var the value undef. You can assign $var what you intended with:

    my $var; @{$var}{ qw( one two red blue )} = ('fish') x 4;

    Update: I thought you wanted to know why no error. Adapting slices to your real data:

    my $ext = {}; for (keys %$mime) { my $case = { description => $_, icon => $mime->{$_}{icon}, }; my @exts = @{$mime->{$_}{ext}}; @{$ext}{@exts} = ($case) x @exts; }

    After Compline,
    Zaxo

Re: strict and warnings but no error?
by japhy (Canon) on May 28, 2003 at 02:13 UTC
    What you did try is the same as writing [10, 20, 30, 40]->[2], except you're using a hash ref instead of an array ref. My code returns 30, yours returns undef, because you didn't supply a hash key "fish".

    I think you want map $_->{ext}, values %mime, but I might be mistaken.

    _____________________________________________________
    Jeff[japhy]Pinyan: Perl, regex, and perl hacker, who'd like a job (NYC-area)
    s++=END;++y(;-P)}y js++=;shajsj<++y(p-q)}?print:??;

Re: strict and warnings but no error?
by cLive ;-) (Prior) on May 28, 2003 at 02:26 UTC
    Can I just clarify that I know the initial code is wrong!!!.

    Please re-read the post and understand. For clarity, it's easiest to store the data in the format of my example. For practicality, I need to use the values in ext as keys in a new hashref, eg:

    my $hashref = { 'cgi' => { icon => 'script.png', description => 'Perl' }, 'pm' => { icon => 'script.png', description => 'Perl' }, 'pl' => { icon => 'script.png', description => 'Perl' }, };

    To sum up:

    • why doesn't the initial example die when it should? If I change the intitial hashref to an arrayref it does die as expected.
    • what's the quickest way of transforming the stored data structure to the usable format? Just being lazy and trying to avoid unecessary duplication :)

    cLive ;-)

    --

    Update: Ahh, thanks japhy :)