Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

Re: Re: What should be returned in scalar context? (best practice)

by Juerd (Abbot)
on Dec 21, 2003 at 17:13 UTC ( #316215=note: print w/ replies, xml ) Need Help??


in reply to Re: What should be returned in scalar context? (best practice)
in thread What should be returned in scalar context?

The right "default" behavior, in my opinion, is to return @ret; and let the programmer using your function sort it out. Document that your function returns an array and be done with it.

No, please don't!

Document that it returns a list. It's not possible to return an array. It is possible to return an array reference, but this code is not doing that. If you document that some functions returns an array, the user can only guess: is it a list or an array reference?

Document that your function returns a list and be done with it.

Juerd # { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }


Comment on Re: Re: What should be returned in scalar context? (best practice)
Re: Re: Re: What should be returned in scalar context? (best practice)
by ysth (Canon) on Dec 21, 2003 at 17:42 UTC
    But if you say return @ret
    you aren't returning a list when called in scalar context. You have to say return @ret[0..$#ret]
    for that.

      But if you say return @ret you aren't returning a list when called in scalar context.

      While that is true, it is *never* returning an array in any context. At least when you say list, that's some indication you should use the sub in list context :)

      Juerd # { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }

      Seven years later I come to this thread and wonder why what you said here got no real attention.

      And seven years later, I still agree with (nearly) everything I myself said in this thread.

      Pedantry be damned. It's nice enough ammo for meaningless flame wars on sites like this one but when people are actually working together on a common goal and not pulling out their micrometers for a geek pecker measuring contest, I've learned that many of them are too smart to bother being pedantic.

      Thank heavens for that.

      Anyway, I'm still saying "returns an array" and everything is moving along as smooth as I might hope. Turns out that telling people what I am doing works just fine. (They've already learned what Perl does.)

      And here was the crux of it all along. When I return an array (sub foo { @a = qw/2 4 6 8/ }) it simply doesn't behave the same as when I return a list (sub bar { qw/2 4 6 8/ }). Go figure. And with my convenient shorthand, I don't have to explain about this context or that one and get into petty details unless I'm doing something strange. Like using wantarray.

      Makes you wonder if Perl was slapped together by a some crazy linguist or something.

      -sauoq
      "My two cents aren't worth a dime.";

        Ditto. (Long time no see. How's tricks?:)

Re: Re: Re: What should be returned in scalar context? (best practice)
by sauoq (Abbot) on Dec 21, 2003 at 19:16 UTC
    Document that it returns a list. It's not possible to return an array.

    No. I would (will and do) document that it returns an array. What you are saying might be true from an internals standpoint, but that's irrelevant. Read the code: return @ret; . . . it says "return" and is followed by an array. More importantly, it behaves like an array. It doesn't behave like a list literal (a slice does, however, as ysth points out.) It certainly doesn't behave like an array reference. Documenting that it returns an array is the only clear way to describe its behavior.

    If you document that some functions returns an array, the user can only guess: is it a list or an array reference?

    When a funtion returns an array reference, document that it returns an array reference. "Array" and "array reference" are not synonyms. The user doesn't have to guess! He just has to read.

    If you sometimes describe a reference to an array as "an array", then you are being sloppy and you should stop.

    -sauoq
    "My two cents aren't worth a dime.";
    

      Read the code: return @ret; . . . it says "return" and is followed by an array.

      print @foo; does not print an array, it prints a list.

      More importantly, it behaves like an array.

      Only in two ways. It returns a number of elements in scalar context and a list of elements in list context. That's where the comparison ends.

      You can't splice what your function returns, push onto it, shift from it, unshift onto it, pop from it, reference it as an array, tie it, assign to it or undef it.

      It is not an array. Don't call it an array, because it simply is not an array. You say it behaves like an array, but it does not. The very things that make an array an array do not apply. Just some context sensitivity, but that does not make your list or number an array.

      If you don't want to call it a list because in scalar context it returns a number of elements, specify both behaviours in your documentation. That's what perl's documentation also does. See grep, keys, split, etcetera.

      "Returns a list" is wrong when the sub is called in scalar context. "Returns an array" is wrong in every possible context. Note that "array context" does exist and your sub cannot be used in it.

      Only an lvalue sub can return an array, but that cannot be done using the return keyword.

      It doesn't behave like a list literal

      Indeed. It does not behave like a list *literal*. But in list context, it does behave like a list, in every single way. It's important to know that there are two kinds of lists, and that list literals are special with syntax; other than that, they're just lists.

      Documenting that it returns an array is the only clear way to describe its behavior.

      No, no, no, no, NO! It's the most vague way to describe its behaviour. Don't call it clear, because it is the very opposite of clear! If you want to be absolutely clear, you must specify the difference in behaviour for every context, or modify the sub so that it really does behave like an array, or like a list.

      "Array" and "array reference" are not synonyms.

      Correct. But why do you think that "list" and "array" are synonyms? They're not. My point is not that "returns an array" would imply it being a reference. My point is that it's entirely unclear whether it returns a list or a reference to an array. It's not returning an array, that's for sure (since you use the return keyword, we're not talking about an lvalue sub here).

      If you sometimes describe a reference to an array as "an array", then you are being sloppy and you should stop.

      I could not agree more.

      I'd like to add this one:
      If you sometimes describe a list as "an array", then you are being sloppy and you should stop.

      Juerd # { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }

        Juerd, I am perfectly aware that functions always return a list. Does that mean I'm going to stop documenting that a function like sub f { return 0 } "returns a scalar?"

        No.

        Somehow I doubt you'd take issue with that even though it isn't technically true. That function is, afterall, returning a list. The list simply has one element. Your argument, if applied evenly, would require the abolishment of the phrase "returns a scalar" as well. Fortunately, we won't have to do that, because your position is completely untenable.

        By saying your function "returns a scalar" or "returns an array" or "returns a list" you are able to describe exactly how code the is written without trying to describe how Perl works.

        The reason it makes sense to say those things is that context is imposed before the value is returned. When you return @ret; the list returned is composed of elements generated by evaluating @ret in the required context. If it is in scalar context, you get the number of elements of @ret. If it is in list context, you get all of the elements of @ret. Likewise, if you return (33, 42); the list returned is created by evaluating (33, 42) in scalar or list context as necessary.

        In other words, there is always a disconnect between what you return and what Perl returns. If you return (33, 42); and your function is called in scalar context, the function returns (42).

        I document what I do. Perl is already well-documented.

        -sauoq
        "My two cents aren't worth a dime.";
        
      I would (will and do) document that it returns an array...When a funtion returns an array reference, document that it returns an array reference.

      Ummm. Perhaps it just has to do with the way I've been taught to document my code but documenting that a subroutine returns an array is very ambiguous especially considering the fact that you can have a subroutine detect context and return the contents of the array for list context and an arrayref in scalar context (this is the behavior I actually expect when the documentation says array because part of my job involves using mod_perl where you need to watch memory consumption). Of course, you could also have it return the number of elements in scalar context. However, just saying that it returns an array can most certainly be a cause for confusion. Since the purpose of documentation is to make certain that the reader clearly understands how to use your module, avoid using "returns an array".

        documenting that a subroutine returns an array is very ambiguous especially considering the fact that you can have a subroutine detect context and return the contents of the array for list context and an arrayref in scalar context (this is the behavior I actually expect when the documentation says array

        Well, if the function returns an array reference in scalar context, the documentation should state that it "returns an array reference in scalar context." Simple as that. An "array" is not an "array reference" and to expect it to become one in scalar context is ridiculous.

        Just take these two functions:

        sub f1 { return my @x = (33, 42) } sub f2 { return (33, 42) }
        To document that the first returns a list and the second returns an array is perfectly acceptable (preferable, imho.) When you see f1() in the code, you know how it is going to act. Number of elements: my $nelts = f1(); ... First element: my ($first) = f1(); ... similarly, when you see f2() in the code, you can know how it will act. Last element: my $last = f2(); ... First element: my ($first) = f2(); (This is exactly why this discussion came up in the first place. Read the first node in this thread to orient yourself.)

        Juerd's mumblings (or ravings) about Perl builtins are quite irrelevant. Besides the fact that every single one of them is a special case, they aren't implemented in Perl to begin with; they are implemented in C.

        The phrase "returns an array" is a very nice way of explaining exactly what you mean without addressing every context separately. I won't avoid it.

        Update: Examples flipped. Thanks jarich for pointing that out. (I actually flipped my description, because I wanted to talk about list values first, and forgot to flip my examples.

        -sauoq
        "My two cents aren't worth a dime.";
        

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://316215]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others lurking in the Monastery: (8)
As of 2014-10-22 12:48 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    For retirement, I am banking on:










    Results (118 votes), past polls