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

Fellow monks...

I'm banging through Perl Objects, References and Modules to get my head around references and complex data structures. At the same time, I'm writing a set of sub-routines to automate a telnet session and parse the resulting text from that session. In trying to integrate what I'm learning in the book to this work, I decided to write some of the subs to return references to hashes or arrays; however, it didn't take me very long to get in trouble. The simple ( and pointless ) code below illustrates the issue:

#! /usr/bin/perl use strict; use warnings; my $ref = return_ref(); if ( !ref ) { print "No hash reference.\n"; } else { print "We have a hash reference.\n"; } sub return_ref { my %hash; return \%hash; }

To my initial surprise, the code above printed "We have a hash reference.", even though the hash I've referenced is empty ( ie: no keys and no values ).
I've since figured out that I need to de-reference the reference before checking for truthfulness. I'm guessing this is because the code above is checking for truthfulness on the memory address of the empty hash ( which should always be true, ie: > 0 ) and not on the hash itself?

Is this correct? Or am I missing something?
Thanks in advance!
njcodewarrior

Replies are listed 'Best First'.
Re: Truthfulness of references
by ikegami (Patriarch) on Mar 13, 2007 at 03:28 UTC

    To my initial surprise, the code above printed "We have a hash reference.", even though the hash I've referenced is empty ( ie: no keys and no values ).

    No matter how many keys it hash, it's still a hash. ref(\%hash) returns HASH, which is a true value. if (%$hash_ref) will tell you if the referenced hash is empty or not.

      Thanks ikegami.

      So I should use:

      if ( %$hash_ref )

      to check whether the hash is empty or not?

      By the way, thanks for your reply on this. I haven't used the Chatterbox before, so I wasn't sure how to respond ( I've been meaning to read up on it, but haven't found the time ).

      njcodewarrior

        Yes, when $hash_ref holds a reference to a hash.

        If $hash_ref doesn't hold a reference to a hash, you'll get a warning or a runtime error depending on what it holds and whether use strict 'refs'; is active or not.

Re: Truthfulness of references
by GrandFather (Saint) on Mar 13, 2007 at 03:14 UTC

    return_ref, as its name announces, returns a reference to a hash. That reference gets assigned to a scalar variable ($ref) as is fine an proper. A rather bogus test for "truth" is then made to see if $_ is a reference to anything (is that what you thought the test actually was?).

    I'm not sure what issue you are trying to illustrate, however the following code may provide a little illumination:

    use strict; use warnings; my $scalar = 'a string is a scalar'; print ref ({}), "\n"; print ref ([]), "\n"; print ref (ret_hash ()), "\n"; print ref (ret_array ()), "\n"; print ">", ref ($scalar), "<\n"; print ref (\$scalar), "\n"; sub ret_hash {my %hash; return \%hash;} sub ret_array {my @array; return \@array;}

    Prints:

    HASH ARRAY HASH ARRAY >< SCALAR

    ref tells you something about the type of reference you point it at (but nothing about scalars). ref on it's own tells you about whatever reference $_ contains (which is the test you were making in your if).


    DWIM is Perl's answer to Gödel

      Thanks GrandFather. That's what I thought the test was actually doing

      So what's a good way to test for truth here?
      The reason for the post is that I've written a few subroutines that either return a reference to a complex data structure OR filter entries out of the previously created data structure. The problem I noticed was that if I ended up filtering out all of the entries and returning a reference to the filtered data structure, my test for truth returned unexpected results ( ie: it returned true eventhough the data structure was empty.

      3 follow up questions:
      1. Should I be returning references from these types of sub-routines?
      2. If so, what's the best way to return them?
      3. What's a good way to test for truthfulness:

      if ( %$ref ) { ...do something }

      or...

      if ( %$ref && ref $ref eq 'HASH' ) { ...do something }

      Thanks again for your help.
      njcodewarrior

        You wrote:

        3. What's a good way to test for truthfulness:

        "Truthfulness" is an unusual term for the boolean value of something. "Truth value" is more common.

        if ( %$ref ) { ...do something }
        That code is fine if you know that $ref holds a hash ref and you need to decide whether the hash is empty.

        or...

        if ( %$ref && ref $ref eq 'HASH' ) { ...do something }
        Here, it seems, you want to check whether the reference you have is indeed a hash ref, but put this way the condition is pretty much useless. Since you try a hash dereference first, if the ref isn't a hash ref your code will die before it gets to the test.

        You'd have to swap the parts for them to make sense:

        if ( ref $ref eq 'HASH' && %$ref ) {
        Anno
Re: Truthfulness of references
by grinder (Bishop) on Mar 13, 2007 at 09:25 UTC

    The other answers have given you some good background information, but just to fill you in with what you need:

    sub return_ref { return if rand < 0.3; my %hash; $hash{foo} = 'bar' if rand < 0.5; return \%hash; } my $ref = return_ref(); if (ref($ref) eq 'HASH' and %$ref) { print "We have a non-empty hash reference.\n"; } else { print "No hash reference, or empty hashref.\n"; }

    Run that a couple of times and observe the behaviour.

    • another intruder with the mooring in the heart of the Perl