Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

Testing array of hash values

by legLess (Hermit)
on Dec 11, 2001 at 07:06 UTC ( #130850=perlquestion: print w/replies, xml ) Need Help??

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

Monks ~

Two questions here:

  1. Why doesn't this work like I expect ("false expectations" is my best answer, but it isn't helping me),
  2. Is there a better way to do what I'm attempting?

I want to format and display a heading iff that heading's children contain data.

#!/usr/bin/perl -T use strict; use warnings; # prints nothing, as expected print do_head( "Empty" ); # prints "<H4>Appearance</H4>"; wish it didn't my @p{ 'eyes', 'hair', 'etc' } = (); print do_head( "Appearance", @p{ 'eyes', 'hair', 'etc' }); #------------------------------------------------ sub do_head { my $heading = shift; my @data = @_; return "<H4>$heading</H4>" if @data; }

I expected the do_head sub to put an empty list into @data; said list would then evaluate as false in a scalar context. This doesn't work, of course, which is why I'm here. I'm sure this is based on my faulty understanding of arrays and hashes. I've re-read the Camel on this subject and not attained enlightenment. Help?

Thanks
--
man with no legs, inc.

Replies are listed 'Best First'.
Re: Testing array of hash values
by athomason (Curate) on Dec 11, 2001 at 07:52 UTC
    Like dws, I'm surprised this would run; it doesn't for me under 5.6.1. Your declaration of %p almost has the syntax for a hash slice, except that you can't do that in a my declaration. Something like my %p; @p{ 'eyes', 'hair', 'etc' } = (); would be legitimate, if unusual.

    As for why do_head doesn't do what you think, I believe you're misunderstanding the behavior of undef in an array. undef in an array or hash doesn't just disappear, it's still something. This is notably different from its behavior in a list (which is not an array!). For instance, see the behavior of this snippet:

    @a = ( ); @c = ( undef ); die "a" if @a; die "b" if ( undef, undef ); die "c" if @c

    Particularly, it dies with 'c', not 'a' or 'b'. In a boolean context--like an if statement--an array takes the value of its length, not its members. In my example, this is 1, which is a true value. Likewise, your three undefs give @data a true value. So, your list of undefs is in fact true when assigned to an array. You were probably expecting the behavior of a list, which in a boolean context evaluates to its last element (e.g., die "d" if ( 1, undef ); die "e" if ( undef, 1 ); dies with 'e'). The solution, if you wish to keep the behavior of printing when the elements are defined, can be found in dws' post.

Re: Testing array of hash values
by dws (Chancellor) on Dec 11, 2001 at 07:26 UTC
    It looks like this is intended to be a CGI, and yet it doesn't emit the correct response header, so I'll assume this is just a code fragment.

    What, exactly, do you expect   @p{'eyes', 'hair', 'etc'} =(); to do? It rather looks like a syntax error to me. If you're trying to pre-load a hash with keys, you might try

    my %p; $p{$_} = undef for qw(eyes hair etc);
    But that begs the question of what your do_print is trying to do, since   @p{ 'eyes', 'hair', 'etc' } results in a three element array, with each element being undef. Assuming that you're trying to return the heading if and only if any one of the elements is present, you could do
    sub do_head { my($heading, @data) = @_; return "<h4>$heading</h4>" if grep { defined($_) } @data; return ""; }

      He may have been trying for:

      my %p; @p{ qw( eyes hair etc ) } = ( undef ) x 3;

      Of course that's crufty in that you have to hard code in the number of elements.

        Actually,
        my %p; @p{'eyes', 'hair', 'etc'} = ();
        is a common idiom for using a hash slice to load a hash with keys and undef values.
      Yes, it's a fragment, but it runs as it should from the command line. The line
      @p{'eyes', 'hair', 'etc'} =();
      is just to show that those keys are empty. It was indeed the undef that was getting me. Your code works. Thanks.
      --
      man with no legs, inc.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://130850]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others exploiting the Monastery: (2)
As of 2021-12-09 03:13 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    R or B?



    Results (36 votes). Check out past polls.

    Notices?