http://www.perlmonks.org?node_id=587433

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

Please review the following code:
#! /usr/local/bin/perl %test = ( test1 => '1', test2 => '2', test3 => '3'); $test = ( test1 => '1', test2 => '2', test3 => '3'); $count1 = keys %test; $count2 = keys %{$test}; print $count1,"\n"; print $count2,"\n";

Returns the following:

3
0


What is the difference between the two hashes besides the obvious that one is referenced.

Thanks,
Logan

Replies are listed 'Best First'.
Re: Counting keys in a referenced hash
by Sidhekin (Priest) on Dec 02, 2006 at 20:06 UTC

    You are using symbolic references. Your second hash is in fact %3. If you had been using strict, you'd have known:

    Can't use string ("3") as a HASH ref while "strict refs" in use ...

    You would get a real hashref (which you are obviously trying to get), if you had used the hash constructor, {...}, instead of the parentheses.

    But the real lesson you should learn here, that might save you both time and future embarrassment, is the same old:

    use strict; use warnings;

    print "Just another Perl ${\(trickster and hacker)},"
    The Sidhekin proves Sidhe did it!

Re: Counting keys in a referenced hash
by tomazos (Deacon) on Dec 02, 2006 at 20:07 UTC
    The second one should be written with curly brackets not parenthesis.

    $test = { test1 => '1', test2 => '2', test3 => '3'};

    Otherwise you are trying to assign a list to a scalar. use warnings would have told you this:

    Useless use of constants in void context at test.pl line 12.

    This is referring to the members of the list that were discarded when it was assigned to a scalar. Everything but the last 3 was discarded.

    Further use strict would have told you:

    Can't use string ("3") as a HASH ref while "strict refs" in use at tes +t.pl line 19.

    $test holds the number 3. When you try to dereference the number 3 (a la %{$test} it converts it to a string "3" and then looks up the hash called "%3" in the symbol table. strict doesn't allow such shenanigans.

    The curly brackets in the correct example indicate an anonymous hash reference. References are scalars. So it assigns to $test just fine.

    Don't study too hard though - the confusion between references-to-objects and the objects themselves will be going away in Perl 6. (or getting worse, depending how you look at it, :) )

    -Andrew.

Re: Counting keys in a referenced hash
by mickeyn (Priest) on Dec 02, 2006 at 20:08 UTC
    $test doesn't refer to a hash ...
    it actually gets the last element from the list which is '3'.

    apply the following change:

    $test = { test1 => '1', test2 => '2', test3 => '3'};
    HTH, Mickey
Re: Counting keys in a referenced hash
by ocs (Monk) on Dec 02, 2006 at 20:11 UTC
    Hi Logan, your second thing what you consider to be a hashref isn't really one. You have to create a anonymous hashref with these curly brackets "{". This is what you mean:
    $test = { test1 => '1', test2 => '2', test3 => '3'};
      Thank you everyone. All I have to say is "Doh!". Thanks again

      Logan
        Actually there is something else you could say, and that's that you will heed the advice to always 'use strict' and 'use warnings'.
Re: Counting keys in a referenced hash
by dimwit (Acolyte) on Dec 03, 2006 at 21:33 UTC
    Not to nitpick but is this homework or just persoanl curiosity? If it is homework I think you should so state. Personally I am willing to help in either case but I do like to know. Other than that I can only say what everyone else has said:
    use warnings; use strict;
    There is no better habit to develope when writing Perl.
    xenchu the dim (ie. dimwit)

    Well, 'splain it to me!

      I understood your opnion,but a newbie might be confused.:-)
      Xenchu,

      This is not for a homework assignment other than I'm a perl hobbyist and learned a very embarrasing lesson today in the monastary.

      Thanks though for the feedback,

      Logan

      s;;5776?12321=10609$d=9409:12100$xx;;s;(\d*);push @_,$1;eg;map{print chr(sqrt($_))."\n"} @_;
Re: Counting keys in a referenced hash
by Anonymous Monk on Dec 03, 2006 at 13:50 UTC
    %test is a hash; $test is a scalar with value 3

    Possibly, $test = { test1 => '1', test2 => '2', ... }; was meant.

    Follow-up question: Why does $test have a value of 3 and not 6?
         ... since ( test1 => '1', test2 => '2', ... ) is the same as ( 'test1, '1', 'test2', '2', ... )
      Dear Anonymus Monk,

      $test doesn't have a value of 6 because unlike an array variable a list literal doesn't evaluate to the number of elements if used in scalar context but to its last element. Try

      #!/usr/bin/perl use strict; use warnings; my $scalar = qw/one two three/; my @array = qw/one two three/; print '$scalar is ', $scalar, "\n"; # prints + 'three' print '@array in scalar context is ', scalar @array, "\n"; # prints + 3

      for example. Perl supposes you know the length of a literally coded (i.e. hard-coded) list anyway and tries to offer you something more useful when it discovers a "Useless use of a constant in void context"...
Re: Counting keys in a referenced hash
by jonathanu (Novice) on Dec 05, 2006 at 21:09 UTC
    I think that your second assignment is not doing what you expect:
    $test = ( test1 => '1', test2 => '2', test3 => '3');
    This assigns the last value in the list to $test. Later, when you dereference it, treating it like a reference to a hash, you end up with an empty hash. Probably you meant to do this instead:
    $test = { test1 => '1', test2 => '2', test3 => '3'};
    The curly braces give you a reference to a hash. This should give you the expected result.
    -JonathanU