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

Dear Monks,

The following print statement prints 2/8 rather than the contents of the hash.
my %newHash = ("key1","value1","key2","value2"); print "\n".%newHash;
The problem only occurs if i place the "\n" in front of %newHash in the print statement. Can anyone please explain this.

Thanks
Gaurav
"Wisdom begins in wonder" - Socrates, philosopher

Replies are listed 'Best First'.
Re: Hash problem
by kyle (Abbot) on Nov 08, 2007 at 03:12 UTC

    The dot operator puts the hash in a scalar context. In perldata, it is written,

    If you evaluate a hash in scalar context, it returns false if the hash is empty. If there are any key/value pairs, it returns true; more precisely, the value returned is a string consisting of the number of used buckets and the number of allocated buckets, separated by a slash.

    It might be instructive to see also Seeking explanation on assigning a hash to a scalar.

Re: Hash problem
by GrandFather (Saint) on Nov 08, 2007 at 02:57 UTC

    which is exactly what would be expected when you stringify a hash. What did you expect to see? One of the following maybe:

    my %newHash = ("key1","value1","key2","value2"); print "Keys: ", join ' ', keys %newHash, "\n"; print "Values: ", join ' ', values %newHash, "\n"; print "Keys and values: ", join (' ', map {"$_ $newHash{$_}"} keys %ne +wHash), "\n";

    Prints:

    Keys: key2 key1 Values: value2 value1 Keys and values: key2 value2 key1 value1

    Perl is environmentally friendly - it saves trees
Re: Hash problem
by toolic (Bishop) on Nov 08, 2007 at 03:07 UTC
    It seems to have more to do with the concatenation operator than the newline character. The . preceding the hash seems to force the hash into a scalar context. For example, try this:
    print scalar %newHash;
    This also produces "2/8".

    Also try this:

    print "foo " . %newHash;
    This produces:
    foo 2/8

    I'll admit that I do not understand the significance of the "2/8".

Re: Hash problem
by LassiLantar (Monk) on Nov 08, 2007 at 03:28 UTC

    I am definitely no expert on this, but my understanding is that the problem here has to do with context. The idea is that expressions return different values depending on their context. In list context, expressions are expected to return lists. In scalar context, expressions are expected to return scalars. In list context (which is what you've got without the "\n".), you get a list of keys and values which get printed like any list of things passed to print. In scalar context (which is what you get with the concatenation), you get 2/8, where 2 is the number of items currently in the hash table and 8 is the number of buckets in the hash table.(1) (It's basically telling you the current load factor. If "load factor" and "buckets" don't make sense, read up on hash tables... Wikipedia's article isn't so bad for a start.)

    Concatenation forces an expression forces the expression into scalar context. It's that scalar contextualness (1) that forces the hash into producing the 2/8. (2) Note that:

    my %newHash = ("key1","value1","key2","value2"); print scalar %newHash; //scalar method forces scalar context

    also prints:

    2/8

    Bibliography (aka "Stuff I n00bishly read in trying to compose this answer"):
    -http://perl.plover.com/context.html
    -NEVER a list in a scalar context -- PLEASE!
    -http://www.itworld.com/nl/perl/03012001/

    (1): Yes, I made that word up.

    (2): I can't say that I'm really doing megaurav2002's question justice here. Question for someone more knowledgeable than I: does %newhash constitute an expression here? I know that in some sense, evaluating a "hash in scalar context" returns "(number of keys in the hash) / (the number of buckets in the table)" and evaluating a "hash in list context" returns the actual keys/values smushed together into a string. However, posts like NEVER a list in a scalar context -- PLEASE! from people like merlyn make me quiver in my boots, so I don't know whether I'm correct to refer to evaluating a "hash in (blank) context".

    Edit: Thank you to kyle for a refrence to TFM. I should have R'd it.

Re: Hash problem
by johngg (Canon) on Nov 08, 2007 at 10:59 UTC
    Your code would have worked if you had used a comma (list separator) to keep the hash in list context rather than the dot (concatenate) which used it in scalar context. As an aside, you can't interpolate a hash into a double-quoted string as you can with an array. However, you can get around that using the @{[ ... ]} construct; I think some call it the babycart operator.

    $ perl -le ' > %hash = ( key1 => q{val1}, key2 => q{val2} ); > print qq{Scalar: }, scalar %hash; > print qq{List: }, %hash; > print qq{Interpolate: %hash}; > print qq{Interpolate in \@{[...]}: @{ [ %hash ] }};' Scalar: 2/8 List: key2val2key1val1 Interpolate: %hash Interpolate in @{[...]}: key2 val2 key1 val1 $

    Cheers,

    JohnGG

Re: Hash problem
by lackita (Sexton) on Nov 08, 2007 at 07:14 UTC
    You can always print out the contents of a hash fairly easily with Data::Dumper
    use Data::Dumper; print "\n" . Dumper \%newHash;
      Forgive my ignorance, but where is the library function Data::Dumper located? I don't see it in any of the 3 Perl books I am using as reference.
        Sorry I didn't respond sooner, haven't checked my account in a while. You can find Data::Dumper on CPAN. Also, what books are you using, because it's in 2/3 of the books that I have.