could you use array or string as hash key in Perl?

Discussion in 'Perl Misc' started by Summercool, Sep 19, 2007.

  1. Summercool

    Summercool Guest

    could you use array or string as hash key in Perl?

    and then what if you modify the array or string internally?

    i tried

    @a = (3,4);

    $h{@a} = "ha";

    and it took @a as the number 2.
    Summercool, Sep 19, 2007
    #1
    1. Advertising

  2. Summercool

    Paul Lalli Guest

    On Sep 19, 8:50 am, Summercool <> wrote:
    > could you use array or string as hash key in Perl?


    Array, no. String, yes.

    Keys are scalars. If you try to use a non-scalar as a key, that non-
    scalar is evaluated in scalar context.

    > and then what if you modify the array or string internally?
    >
    > i tried
    >
    > @a = (3,4);
    >
    > $h{@a} = "ha";
    >
    > and it took @a as the number 2.


    Right. Because an array in scalar context returns its size. The size
    of @a is 2.

    I suppose you could use the stringified version of a reference to the
    array as the key:
    $h{\@a} = "ha";
    but I have no idea why you would want to do such a thing.

    What are you *trying* to do? What is your end goal?

    If you're trying to make a multidimensional structure, you should read
    up on references:
    perldoc perlreftut
    perldoc perllol
    perldoc perldsc

    Paul Lalli
    Paul Lalli, Sep 19, 2007
    #2
    1. Advertising

  3. Summercool

    Ben Bullock Guest

    On Wed, 19 Sep 2007 12:50:10 +0000, Summercool wrote:

    > could you use array or string as hash key in Perl?
    >
    > and then what if you modify the array or string internally?
    >
    > i tried
    >
    > @a = (3,4);
    >
    > $h{@a} = "ha";
    >
    > and it took @a as the number 2.


    That is the answer to your question, in fact. Perl doesn't like your array
    in its hash argument, so it decides to change your array into a scalar. The
    number 2 is the "scalar value" of your array, which is the number of
    elements in the array.

    Thus Perl has already told you that you can't use an array as a hash key.

    Of course you can use a string as a hash reference. To find out what Perl
    does if you change the value of the string, write a simple test, run it
    and see what happens.

    #!/usr/bin/perl
    use warnings; use strict;
    my $string = "frog";
    my %animals;
    $animals{$string} = "amphibian";
    $string = "dolphin";
    print $animals{$string}, "\n";
    print $animals{frog}, "\n";
    Ben Bullock, Sep 19, 2007
    #3
  4. On Wed, 19 Sep 2007 12:50:10 -0000, Summercool
    <> wrote:

    >could you use array or string as hash key in Perl?


    A hash key in current Perl can *only* be a string.

    If you want to use an array you have to specify your own array to
    string conversion facility in a way that is suitable for the problem
    at hand. A simple "@array" may be appropriate or totally wrong,
    depending on the actual situation.

    >and then what if you modify the array or string internally?


    "Internally" as opposed to... what?

    >i tried
    >
    >@a = (3,4);
    >
    >$h{@a} = "ha";
    >
    >and it took @a as the number 2.


    Of course, because the array is evaluated in a scalar context and in a
    scalar context an array is its size.

    You may want to use the reference to the array, in which case the key
    will stay the same also if you modify the array later. You just have
    to know that the key will *not* be the reference, but also in this
    case, its stringification: i.e. do not hope to recover the array
    directly from the key, although that is not what you were asking for.
    Incidentally, if you want to, then there's a suitable module to do
    exactly that.


    cognac:~ [16:06:18]$ perl -MData::Dumper -e '@a=3..4; print Dumper \
    { "@a" =>1, \@a => 2 }'
    $VAR1 = \{
    'ARRAY(0x814fe34)' => 2,
    '3 4' => 1
    };
    cognac:~ [16:06:25]$ perl -le '@a=3..4; $h{"@a"}=3; push @a,1; \
    print $h{"@a"} || "undef"'
    undef
    cognac:~ [16:06:33]$ perl -le '@a=3..4; $h{\@a}=3; push @a,1; \
    print $h{\@a} || "undef"'
    3


    Michele
    --
    {$_=pack'B8'x25,unpack'A8'x32,$a^=sub{pop^pop}->(map substr
    (($a||=join'',map--$|x$_,(unpack'w',unpack'u','G^<R<Y]*YB='
    ..'KYU;*EVH[.FHF2W+#"\Z*5TI/ER<Z`S(G.DZZ9OX0Z')=~/./g)x2,$_,
    256),7,249);s/[^\w,]/ /g;$ \=/^J/?$/:"\r";print,redo}#JAPH,
    Michele Dondi, Sep 19, 2007
    #4
  5. On Wed, 19 Sep 2007 14:06:52 +0000 (UTC), Ben Bullock
    <> wrote:

    >That is the answer to your question, in fact. Perl doesn't like your array
    >in its hash argument, so it decides to change your array into a scalar. The
    >number 2 is the "scalar value" of your array, which is the number of
    >elements in the array.
    >
    >Thus Perl has already told you that you can't use an array as a hash key.


    This is misleading: using a bare array as hash key is perfectly valid
    syntax with an acceptable semantics. So you *can* "use an array as a
    hash key": it simply won't do what the OP wanted, whatever it was.


    Michele
    --
    {$_=pack'B8'x25,unpack'A8'x32,$a^=sub{pop^pop}->(map substr
    (($a||=join'',map--$|x$_,(unpack'w',unpack'u','G^<R<Y]*YB='
    ..'KYU;*EVH[.FHF2W+#"\Z*5TI/ER<Z`S(G.DZZ9OX0Z')=~/./g)x2,$_,
    256),7,249);s/[^\w,]/ /g;$ \=/^J/?$/:"\r";print,redo}#JAPH,
    Michele Dondi, Sep 19, 2007
    #5
  6. Summercool

    Ben Bullock Guest

    On Wed, 19 Sep 2007 16:49:10 +0200, Michele Dondi wrote:

    > On Wed, 19 Sep 2007 14:06:52 +0000 (UTC), Ben Bullock
    > <> wrote:
    >
    >>That is the answer to your question, in fact. Perl doesn't like your
    >>array in its hash argument, so it decides to change your array into a
    >>scalar. The number 2 is the "scalar value" of your array, which is the
    >>number of elements in the array.
    >>
    >>Thus Perl has already told you that you can't use an array as a hash
    >>key.

    >
    > This is misleading: using a bare array as hash key is perfectly valid
    > syntax with an acceptable semantics. So you *can* "use an array as a
    > hash key": it simply won't do what the OP wanted, whatever it was.


    In the original poster's post he says

    > i tried
    > @a = (3,4);
    > $h{@a} = "ha";
    > and it took @a as the number 2.


    so he clearly already knows that using an array as a hash key isn't a
    syntax error.
    Ben Bullock, Sep 19, 2007
    #6
  7. Summercool

    patrick Guest

    On Sep 19, 5:50 am, Summercool <> wrote:
    > could you use array or string as hash key in Perl?
    >
    > and then what if you modify the array or string internally?
    >
    > i tried
    >
    > @a = (3,4);
    >
    > $h{@a} = "ha";
    >
    > and it took @a as the number 2.


    If you want to try and keep the array values you can always use

    $h{ join('.', @a) } = 'ha';

    print " $h{ join('.', @a) }\n";

    ====>Patrick
    patrick, Sep 19, 2007
    #7
  8. Summercool

    Ben Morrow Guest

    Quoth Paul Lalli <>:
    > On Sep 19, 8:50 am, Summercool <> wrote:
    > > could you use array or string as hash key in Perl?

    >
    > Array, no. String, yes.
    >
    > Keys are scalars.


    No, keys are strings (except in tied hashes). This is important, as it
    is why using a ref as a key doesn't work.

    > If you try to use a non-scalar as a key, that non- scalar is evaluated
    > in scalar context.


    ....and then stringified.

    Ben
    Ben Morrow, Sep 19, 2007
    #8
  9. Summercool

    Summercool Guest

    yes, i tried using

    $h{(3,4)} = "hee";

    and print out all the key value pairs.
    the key "3 4" show up with a strange character between them.
    Summercool, Sep 19, 2007
    #9
  10. Summercool

    Ben Morrow Guest

    Quoth Summercool <>:
    > yes, i tried using
    >
    > $h{(3,4)} = "hee";
    >
    > and print out all the key value pairs.
    > the key "3 4" show up with a strange character between them.


    That character is the value of $; (by default "\034"), and is how Perl 4
    used to do multi-level hashes before Perl 5 and refs were invented.
    Using a (literal) list as a key is well worth avoiding nowadays.

    Ben
    Ben Morrow, Sep 19, 2007
    #10
  11. On Wed, 19 Sep 2007 17:27:19 -0000, Summercool
    <> wrote:

    >yes, i tried using
    >
    >$h{(3,4)} = "hee";
    >
    >and print out all the key value pairs.
    >the key "3 4" show up with a strange character between them.


    That's $;


    Michele
    --
    {$_=pack'B8'x25,unpack'A8'x32,$a^=sub{pop^pop}->(map substr
    (($a||=join'',map--$|x$_,(unpack'w',unpack'u','G^<R<Y]*YB='
    ..'KYU;*EVH[.FHF2W+#"\Z*5TI/ER<Z`S(G.DZZ9OX0Z')=~/./g)x2,$_,
    256),7,249);s/[^\w,]/ /g;$ \=/^J/?$/:"\r";print,redo}#JAPH,
    Michele Dondi, Sep 19, 2007
    #11
  12. On Wed, 19 Sep 2007 08:33:18 -0700, patrick <>
    wrote:

    >If you want to try and keep the array values you can always use
    >
    >$h{ join('.', @a) } = 'ha';
    >
    >print " $h{ join('.', @a) }\n";


    How does that work with

    @a=('a', 'b.c');

    and

    @a=qw/a b c/;

    respectively?

    Not to say that your answer is *incorrect* but that one should add
    that some care is required.


    Michele
    --
    {$_=pack'B8'x25,unpack'A8'x32,$a^=sub{pop^pop}->(map substr
    (($a||=join'',map--$|x$_,(unpack'w',unpack'u','G^<R<Y]*YB='
    ..'KYU;*EVH[.FHF2W+#"\Z*5TI/ER<Z`S(G.DZZ9OX0Z')=~/./g)x2,$_,
    256),7,249);s/[^\w,]/ /g;$ \=/^J/?$/:"\r";print,redo}#JAPH,
    Michele Dondi, Sep 19, 2007
    #12
  13. Summercool

    Alex Guest

    Ben Morrow wrote:

    > No, keys are strings (except in tied hashes). This is important, as it
    > is why using a ref as a key doesn't work.


    Why not? Refs can be stringified, no?

    >> If you try to use a non-scalar as a key, that non- scalar is evaluated
    >> in scalar context.

    >
    > ...and then stringified.
    >
    > Ben


    Alex
    --
    localpart = alext
    domain = iki dot fi
    email = localpart at domain
    Alex, Sep 20, 2007
    #13
  14. On Thu, 20 Sep 2007 10:17:38 +0300, Alex <>
    wrote:

    >> No, keys are strings (except in tied hashes). This is important, as it
    >> is why using a ref as a key doesn't work.

    >
    >Why not? Refs can be stringified, no?


    Yes, it can, but he meant exactly what I wrote in another post in this
    thread, i.e. that the stringification is a one-way tranformation, so
    that when accessing the keys of such a hash one can not hope of using
    those as references, which may or may not be what the OP wants, but
    that in case happens to confuse some people. See

    perldoc -q 'reference.*key'


    Michele
    --
    {$_=pack'B8'x25,unpack'A8'x32,$a^=sub{pop^pop}->(map substr
    (($a||=join'',map--$|x$_,(unpack'w',unpack'u','G^<R<Y]*YB='
    ..'KYU;*EVH[.FHF2W+#"\Z*5TI/ER<Z`S(G.DZZ9OX0Z')=~/./g)x2,$_,
    256),7,249);s/[^\w,]/ /g;$ \=/^J/?$/:"\r";print,redo}#JAPH,
    Michele Dondi, Sep 20, 2007
    #14
  15. Summercool

    Uri Guttman Guest

    >>>>> "A" == Alex <> writes:

    A> Ben Morrow wrote:
    >> No, keys are strings (except in tied hashes). This is important, as it
    >> is why using a ref as a key doesn't work.


    A> Why not? Refs can be stringified, no?

    and i use refs for keys in a few places. i have both the keys and values
    are the same refs (of course i know the keys are stringified). it is a
    very good method to use to track a collection of objects or things in
    one place say in a class that needs to also know about all of the
    objects it has created. you either need to use weak refs or a
    delete call on that hash to make sure you don't leak ram.

    uri

    --
    Uri Guttman ------ -------- http://www.stemsystems.com
    --Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
    Search or Offer Perl Jobs ---------------------------- http://jobs.perl.org
    Uri Guttman, Sep 20, 2007
    #15
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. rp
    Replies:
    1
    Views:
    512
    red floyd
    Nov 10, 2011
  2. Une bévue
    Replies:
    5
    Views:
    146
    Une bévue
    Aug 10, 2006
  3. Anthony Martinez
    Replies:
    4
    Views:
    267
    Robert Klemme
    Jun 11, 2007
  4. Michal Suchanek
    Replies:
    6
    Views:
    224
    Nobuyoshi Nakada
    Jun 13, 2007
  5. Srijayanth Sridhar
    Replies:
    19
    Views:
    608
    David A. Black
    Jul 2, 2008
Loading...

Share This Page