in reply to Can't understand function returning undefs

Just like "FOO + BAR" doesn't return "FOO" or "BAR", "FOO = BAR" doesn't necessarily return "FOO" or "BAR". A list assignment in scalar context returns the number of values returned by its RHS.


In detail,

"($x,$y) = a()" is a list assignment, and it is being evaluated in scalar context (from the if()). A list assignment in scalar context returns the number of values returned by its RHS. In this case, that's 2.

"(undef,undef) = a()" is a list assignment, and it is being evaluated in scalar context (from the if()). A list assignment in scalar context returns the number of values returned by its RHS. In this case, that's 2.

"a()" is a function call, and it is being evaluated in scalar context (from the if()). A function called in scalar context evaluates its return expression in scalar context, so "undef, undef" is evaluated in scalar context. The list/comma operator in scalar context evaluates each operand in turn and returns the last value. In this case, that's undef.

"undef, undef" is being evaluated in scalar context (from the if()). The list/comma operator in scalar context evaluates each operand in turn and returns the last value. In this case, that's undef.

Replies are listed 'Best First'.
Re^2: Can't understand function returning undefs
by furry_marmot (Pilgrim) on Sep 29, 2010 at 17:29 UTC
    Retracted after bitter tirade by ikegami. Thanks for setting me straight in such a civil manner.

      This is closely related to the concept of the default input operator

      What are you talking about???

      • $_ is not an operator, at least no more so than $x.
      • Some functions default to using $_ as an argument, but that is unrelated to this thread.
      • $_ has nothing to with input.
      • How can an input operator have anything to do with this?

      And the rest of the post is no better. So many errors!

      sub a{ return 1, 2, 3 } a();

      This evaluates what a() returns, in scalar context. $_ gets the last value returned by a(). In this case, $_ is 3, or True if evaluated in Boolean context. If you tested $x = a(), you'd get the same True result, with $x equal to 3.

      • That code doesn't provide enough information to determine in which context a() is evaluated. If anything, void context is implied.
      • Nothing is assigned to $_.
      • If a() is evaluated in scalar context, then it makes no sense to talk about the last value it returns as it only returns one.

      sub a{ return 1, 2, 0 }  a();

      $_ gets the last value returned by a(), as before. In this case, $_ is 0 in scalar context, or False in Boolean context!

      • Nothing is assigned to $_.
      • The same value is returned by the comma operator in both "boolean context" and scalar context.

      @a = (undef, undef); @a;

      This array is evaluated in scalar context because we haven't done anything to force list context. An array, evaluated in scalar context, is always the number of elements it contains.

      • That code doesn't provide enough information to determine in which context a() is evaluated. If anything, void context is implied.
      • There is no default context.

      sub a{ return 1, 2, 0 } ($x,$y) = a();

      We're still evaluating what a() returns, but here we've forced list context. That means that $_ is assigned the number of elements in the list returned, not the elements. It doesn't matter what a() returns -- if it returns one or more elements, $_ will be set to non-zero, or True in Boolean context.

      • List context isn't being forced, if there is such a thing.
      • Nothing is assigned to $_, so most of that is just nonsense.
      • The same value is returned by the list assignment operator in both "boolean context" and scalar context.

      sub a{ return 1, 2, 0 }  @arr = a();

      Exactly the same as above.

      • List context isn't being forced, if there is such a thing.
      • Nothing is assigned to $_, so most of that is just nonsense.
      • The same value is returned by the list assignment operator in both "boolean context" and scalar context.

      (undef, undef);

      An array is a container for a list. This is NOT an array, and we haven't done anything to force list context, so we have a list of scalars evaluated in scalar context. $_ is set to the last element, which is undef -- or False in Boolean context.

      • There is no default context.
      • That code doesn't provide enough information to determine in which context a() is evaluated. If anything, void context is implied.
      • Nothing is assigned to $_.
      • The same value is returned by the comma operator in both "boolean context" and scalar context.

      sub a { return undef, undef } ($x, $y) = a(); if(not $x && not $y) { print "False\n" }

      I think this is closer to what you're looking for. Whenever you don't specifically lay out the condition you are testing, you are probably testing $_.

      No, it's not what he wants.

      • It doesn't loop.
      • The condition of the "if" statement relies on incorrect assumptions about precedence.
      • A truth test is two levels removed from optiomal. (A defined test would be better, but testing whether the iterator returned anything at all would be best.)

      I hope this helps.

      Pure harm. Good thing the formatting makes it unreadable.