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

Hello All, relatively new to Perl, but have been programming for ages. One thing bothers me a bit, as I can't see why the following line of code would throw an interpreter warning (useless use of hash in void context...)

my $foo = (defined($some_hash{bar}) and $some_hash{bar}));

Obviously the above can be re-written with the ternary operator quite easily:

my $foo = defined($some_hash{bar}) ? $some_hash{bar} : 0;

So I'm not really asking /how/ to solve this issue (another three solutions have presented themselves just in the time it took to type this), I would just like to know /why/ this occurs. Is it just a stupid interpreter, or is there some danger in treating your Perl vars like this? I figured Perl's loose typing might let me get away with such extremely lazy evaluations.

Replies are listed 'Best First'.
Re: Simple Query on Operators
by ikegami (Patriarch) on Mar 04, 2008 at 16:36 UTC

    I can't see why the following line of code would throw an interpreter warning (useless use of hash in void context...)

    It doesn't. It doesn't even compile. I bet the line is really

    my $foo = defined($some_hash{bar}) and $some_hash{bar};

    which is the same thing as

    ( my $foo = defined($some_hash{bar}) ) and $some_hash{bar};

    where the result of defined is assigned to $foo and $some_hash{bar} never is. Perhaps you want

    my $foo = defined($some_hash{bar}) && $some_hash{bar};

    or

    my $foo = ( defined($some_hash{bar}) and $some_hash{bar} );

    Take care, or and and have very low precedence.

      Ah! So it is.

      Silly me, thinking 'and' meant '&&', but when you've written too much C++...

      Thanks much for the help
Re: Simple Query on Operators
by apl (Monsignor) on Mar 04, 2008 at 15:53 UTC
    What exactly are you trying to do in the initialization of $foo? I've always (unthinkly) used the ternary form.
      What prompted this was throwing @_ to a hash, like:

      my ($self, %args) = @_;

      And wanting to allow variables to be optional. The little snippet I posted basically sets a variable to a default if it isn't given in the arguments.

      Again, this is a pointless question in that I don't need to answer it. I'm just curious and always try to figure out how a language "thinks" when I pick it up.
        It's far from pointless. A great way of setting a default is: $foo ||= $hash{key};

        That is, if the variable $foo does not already have a value, give it the value of $hash{key}.

        Another way to do this is with a separate %DEFAULTS hash that gets mixed in with the arguments passed.

        use Data::Dumper; my %DEFAULTS = ( a => 'a default', b => 'b default', c => 'c default', ); my %args = ( a => 'a arg', b => undef, ); %args = ( %DEFAULTS, %args ); print Dumper \%args; __END__ $VAR1 = { 'c' => 'c default', 'a' => 'a arg', 'b' => undef };

        Notice that this method keeps a value that exists but is not defined, so somebody can explicitly pass in undef if they want to. This may or may not be what you want.