in reply to Re: undef==defined sometimes? (body question)
in thread undef==defined sometimes?

So, if I have a function that returns undef on error, else an array with results, I should assign it to a scalar and and see if it is undef, if not, then hope it's a reference to an array?

If I'm "in" the function, and I return an array to a scalar won't perl coerce the array into a scalar length and assign that to my scaler instead? So I'll end up with either the number of elements in the array, or 'unef', but not the array?

Seems like this is pushing me in the direction of not being able to return an array with a list of found values or 'undef' ... I think I 'resent' the syntax that @a=1, is an assignment to $a[0]...I can understand why it happens, but I'm not sure how useful it is given that by using the "@" and no index, I'm only wanting an array to be assigned. It seems a perversity to coerce undef into a defined array with value undef in the first element....

Under what situations is this commonly useful? Or are there too many to number? Sigh. ...

If I want to return 'undef' and have it be interpreted as an undef array, then I need to return ()....a bit of a pain, since I wanted higher level routines to not care about the type of a return unless they needed to use it, with undef always being 'undef'.....

Just seems to complicate matters a bit.

  • Comment on Re^2: undef==defined sometimes? (body question)

Replies are listed 'Best First'.
Re^3: undef==defined sometimes? (body question)
by ysth (Canon) on May 03, 2008 at 00:56 UTC
    Seems like this is pushing me in the direction of not being able to return an array with a list of found values or 'undef' ...
    Right, because it's perfectly valid to return a list with the single value 'undef', and that's indistinguishable from a sub returning 'undef' as meaning 'nothing to return'.
    I think I 'resent' the syntax that @a=1, is an assignment to $a[0]...I can understand why it happens, but I'm not sure how useful it is given that by using the "@" and no index, I'm only wanting an array to be assigned. It seems a perversity to coerce undef into a defined array with value undef in the first element...
    @a=1 is indeed an array operation; it clears any current content in the whole array before assigning to $a[0].

    You'd suffer less confusion if you ditch the idea of "array" being a type of value. Values in perl are either lists or scalars; "array" is a variable type that can store a list (as is "hash", but in a different way).

Re^3: undef==defined sometimes? (body question)
by chromatic (Archbishop) on May 03, 2008 at 05:33 UTC
    I think I 'resent' the syntax that @a=1, is an assignment to $a[0]...

    Why would you resent that and not resent that @a = (1, 2, 3) is an assignment to $a[0], $a[1], and $a[2], respectively? (Don't make the mistake that the parentheses have anything to do with list creation; they only exist for grouping, as the precedence of the assignment operator is higher than that of the comma operator.)

      chromatic, please tell merlyn to incorporate this post into the next Learning Perl ed. (where he says to do @empty = () instead of @not_empty = undef as it would have clarified this concept much sooner for me as well. The info is there but not specifically for this point.
Re^3: undef==defined sometimes? (body question)
by ikegami (Patriarch) on May 03, 2008 at 00:43 UTC

    So, if I have a function that returns undef on error, else an array with results, I should assign it to a scalar and and see if it is undef, if not, then hope it's a reference to an array?

    Functions can *only* return lists of scalars. That list can contain 0, 1 or more scalars. One way to address your problem is to return an empty list (a list with no elements) on error, but that only works if returning an empty list never occurs on success.

    sub func { my ($error) = @_; my @results = ('some', 'values'); # 1 or more values. $error ? () : @results; } for (0..1) { my @results = func($_); print(@results ? "no error (@results)" : 'error', "\n"); }

    Another way is to always return exactly one scalar: undef on error or an array reference on success.

    sub func { my ($error) = @_; my @results = (); # 0 or more values. $error ? undef : \@results; } for (0..1) { my $results = func($_); print($results ? "no error (@$results)" : 'error', "\n"); }
Re^3: undef==defined sometimes? (body question)
by parv (Parson) on May 03, 2008 at 00:25 UTC

    Why don't you just return nothing at all on error, and get over the non-problem problem?

    There was really no point in writing code here in hindsight. So ...

      Well -- I could, but then the calling function would get garbage if I used it in an assignment.

      The function was *supposed* to return a list and only returned undef as an error condition (which wasn't the same as returning an empty list). The undef was reserved for 'illegal operations', like an attempt to compare two strings where one string was undefined. Otherwise, if nothing was found, but no error occurred, it returned a list of size 0 ("()").

      If I didn't explicitly return a value, wouldn't the results of whatever the last calculation be returned, essentially returning "left-overs" by accident? I'd rather return 'undef' and have consistently wrong behavior rather than random behavior -- at least if it is consistently wrong, I'm more likely to notice a problem. :-)

      -l

        If I didn't explicitly return a value, wouldn't the results of whatever the last calculation be returned

        return; return an empty list, just like return ();. If the function result is treated as a scalar, it will see undef.

        If you omit the return entirely, then you get the result of the last expression evaluated.