Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

nonempty false list

by Anonymous Monk
on Mar 10, 2011 at 17:56 UTC ( [id://892467]=perlquestion: print w/replies, xml ) Need Help??

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

Consider the following:
$ perl -e '%x=(1 => 2); if(@x{1, 2}) { print "yes\n" } else { print "n +o\n" }' no
$ perl -e '%x=(1 => 2); if(@{[@x{1, 2}]}) { print "yes\n" } else { pri +nt "no\n" }' yes
Why should these two statements not both print "yes", since both produce a nonempty list?

Replies are listed 'Best First'.
Re: nonempty false list
by toolic (Bishop) on Mar 10, 2011 at 18:15 UTC
    I suspect your 1st line returns no because the slice is being evaluated in scalar context and it is returning the last element in the list, which is undef. I will attempt to search for documentation to support this hypothesis.

    If you switch the 1 and the 2, you get a yes:

    $ perl -e '%x=(1 => 2); if(@x{2, 1}) { print "yes\n" } else { print "n +o\n" }' yes
    When you do the hash slice, you are asking for key 1 (which exists) and key 2 (which does not exist):
    use warnings; use strict; use Data::Dumper; my %x = (1 => 2); my @y = @x{1, 2}; print Dumper(\@y); __END__ $VAR1 = [ 2, undef ];

    Update: see also: Context tutorial

    Update: from Scalar values (emphasis mine):

    If you evaluate an array in scalar context, it returns the length of the array. (Note that this is not true of lists, which return the last value, like the C comma operator, nor of built-in functions, which return whatever they feel like returning.)

      Note that this is not true of lists, which return the last value

      That's referring to the list operator («EXPR,EXPR,...,EXPR»), but it's a hash slice here. Hash slices in scalar context return the last element of the slice too, though.

Re: nonempty false list
by JavaFan (Canon) on Mar 10, 2011 at 18:17 UTC
    Neither produce lists. The if statement provides scalar context.

    In the first case, we have a slice - and the last element of the slice is the return value. Which is undefined. The second case has an array in scalar context. Which produces the number of elements (2 in this case).

Re: nonempty false list
by wind (Priest) on Mar 10, 2011 at 18:20 UTC

    A hash slice in a scalar context returns the last element. @x{1, 2} equals (2, undef) and so undef is used as the boolean.

    The second one constructs a new array, and therefore the array count is returned in a scalar context, 2.

    %x = (1 => 2); print '@x{1, 2} in scalar equals: \'' . (scalar @x{1, 2}) . "'\n"; # Returns '' print '@{[@x{1, 2}]} in scalar equals: \'' . (scalar @{[@x{1, 2}]})) . + "'\n"; # Returns 2
      Hmm thanks to everyone, I definitely see the distinction. What I am TRYING to do is this: I have a hash, and I want to test whether any of three separate keys produce a 'true' value. So, it looks something like this (I boiled it down for the first example)
      if(@opts{qw|a b c|}) { }
      Which seemed pretty elegant, but as previously discussed does not work, because its a hash slice. THIS, however, seems horribly inelegant:
      if(@{[@opts{qw|a b c|}]}) { }
      But perl must have something better than this:
      if($opts{a} || $opts{b} || $opts{c}) { }
        Testing each value of a list sounds like a job for grep. When I need to determine if any elements of a list are true, I will usually use something that looks like:

        if( grep $_, @opts{qw|a b c|}) { }

        A cleaner version of this would be

        if( grep $opts{$_}, qw|a b c|) { }

        You can use a couple negations to check if all values are true:

        if( !grep !$opts{$_}, qw|a b c|) { }

        Note that your second suggestion will always return true, since you will always have a 3-element array in scalar context.

        Just use grep
        if (grep {$opt{$_}} qw(a b c)}) {
        And you can even capture the keys for which true is returned
        if (my @keys = grep {$opt{$_}} qw(a b c)}) { print "@keys match\n";
Re: nonempty false list
by ikegami (Patriarch) on Mar 10, 2011 at 18:57 UTC

    «if» imposes a scalar context on the condition. That means the conditional expression is incapable of returning a list. The list can't possibly be empty, not empty, true or false if it doesn't even exist.

    A hash slice in scalar context returns the last element, so

    if (@x{1,2})
    is the same as
    if ($x{2})

    The following operators evaluate EXPR in list context and count the number of returned values:

    if (@{[ EXPR ]}) # Array if (map 1, EXPR) # map if (grep 1, EXPR) # grep if (() = EXPR) # List assignment if (count(EXPR)) # External function such as # sub count { 0+@_ }

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others pondering the Monastery: (6)
As of 2024-04-23 07:41 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found