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

Hello,

I'm trying to pass an anonymous hash to a sub the laziest way I possibly can. So I'm doing the usual:
get_ids({'id_one' => 1, 'id_two' => 2, 'id_three' => 3})

But what I'd really like to do is something like:
get_ids({'id_one','id_two','id_three'})

This doesn't seem to work. When I shift the hashref to a scalar in the sub the scalar only knows about the first key id_one when I dereference it using a map:
sub get_ids { $id_hashref = shift; map { print "key $_ exists in the request\n" } (keys %{$id_hashref +}); }

Is there a way to pass an anonymous hash to a sub without defining unnecessary values for all of the keys? I could pass an array and make it hash keys in the sub, but I'd really rather not. I have the funny feeling I'm missing something, but its 1am...:)

Thanks,
Alex

Replies are listed 'Best First'.
Re: Pass anonymous hash - keys only?
by gmax (Abbot) on Nov 11, 2002 at 09:29 UTC
    Be aware that your get_ids is using map in void context.

    As for the anonymous hash, you can use map in its rightful list context to create a hash without manually inserting the values.
    #!/usr/bin/perl -w use strict; sub get_ids { my $hashref = shift; print map {"$_\n"} keys %$hashref; # or, depending on your tastes # print "$_\n" for keys %$hashref; } get_ids( {map {$_,1} qw(one two three)} );
    update Added link to Perl FAQ 6.
    _ _ _ _ (_|| | |(_|>< _|
Re: Pass anonymous hash - keys only?
by BrowserUk (Patriarch) on Nov 11, 2002 at 09:42 UTC

    The reason get_ids({'id_one','id_two','id_three'}) doesn't work is because it is taking each pair of values as a key/value pair. So that line is constructing a hash { id_one=>'id_two', id_three=>undef }.

    If you were running with warnings enabled, you would be receiving a message Odd number of elements in hash assignment at... which would have given you a clue here

    Without asking why you want to do this, though from what you've told us it seems bizaar:), you could do

    get_ids( {id_one=>undef, id_two=>undef, id_three=>undef } );

    However, if the idea is that you are going to return the hash to the caller with the values for the keys supplied filled in, it might be better to pass a ref to an anon. array of the values and then construct the hash internally like this.

    sub get_ids { my %hash; @hash{@{shift()}} = undef; print "key:$_\n" for keys %hash; return \%hash; } # Call it this way my $hashref = get_ids( [qw/id_one id_two id_three/] );

    If you run that, you'll get output

    key:id_one key:id_three key:id_two

    Nah! You're thinking of Simon Templar, originally played (on UKTV) by Roger Moore and later by Ian Ogilvy
Re: Pass anonymous hash - keys only?
by sauoq (Abbot) on Nov 11, 2002 at 09:33 UTC
    But what I'd really like to do is something like:
    get_id({'id_one','id_two','id_three'})
    This doesn't seem to work. When I shift the hashref to a scalar in the sub the scalar only knows about the first key id_one
    . . .

    Actually, it knows about two keys in that example: 'id_one' and 'id_three'. The reason is that 'id_two' ends up being the value associated with 'id_one'. A => is really a glorified comma and perl doesn't mind at all if you use a regular comma instead.

    The question you've left us with is: why are you doing that? It looks like you should probably just be passing the arguments normally or perhaps using an array ref. The example you've given seems a bit contrived though, so it's hard to see what problem you are really trying to solve.

    -sauoq
    "My two cents aren't worth a dime.";