in reply to Re: Re: What should be returned in scalar context?
in thread What should be returned in scalar context?

Tilly:
# And for something completely different... sub foo { if (1 != @_) { return map $foo($_), @_; } # body of foo here. return $whatever; }
Abigail-II:
Why the test on the number of arguments, and the recursion? Wouldn't the following be equivalent?:
sub foo { map { # body of foo here. $whatever } @_ }
Tilly:
Answering the last question first, no that isn't equivalent to just have a map since a map in scalar context coerces like an array does - it tells you how many elements that you have, not what any of them are.
The original function also has a map in scalar context problem. Something like this is probably what you want:
sub foo { (map { # body of foo here. $whatever } @_)[0..$#_]; }
Though I this may be clearer:
sub foo { my @ret = map { # body of foo here $whatever; } @_; @ret[0..$#ret]; }

Replies are listed 'Best First'.
Re: Re: Re: Re: What should be returned in scalar context?
by tilly (Archbishop) on Dec 03, 2003 at 20:14 UTC
    You missed the significance of the phrase, The hidden assumption is that it only makes sense to impose scalar context when you are transforming a single element, so behaving badly if you try to transform multiple elements in scalar context is OK. Which is an explicit reference to the misbehaviour that you are pointing out.

    Returning a nonsense result that the programmer will puzzle over makes sense to me because strange answers are a clue that you are doing something wrong. Returning something sort of sensible may make the mistake less immediately apparent. Putting an explicit error makes more sense still - if you want to put the effort out. Retrofitting a 2 line map into an existing function is easier than rewriting it.

Re: Re: Re: Re: What should be returned in scalar context?
by BrowserUk (Patriarch) on Dec 03, 2003 at 21:57 UTC

    I'm puzzled by this

    sub foo { # vvvv Temp array my @ret = map { # body of foo here $whatever; } @_; # <<< list 1 # vvvvvvvv list 2 @ret[0..$#ret]; # ^^^^^^^^^^^^^^ list 3 }

    Why generate one temporary array and three lists to achieve the same effect as

    sub foo { map { # body of foo here $_[ $_ ] ...; $whatever; } 0..$#ret; }

    which creates 2 lists and no temporary array.

    What am I missing?


    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "Think for yourself!" - Abigail
    Hooray!
    Wanted!

      What am I missing?

      Note that the node title mentions "scalar context". This is what you are missing. Compare your two foo()s when called in a scalar context.

                      - tye

        Right tye, ysth pointed this out to me by /msg also.

        If the original version is called in a scalar context when returning the list 'foo', 'bar', 'baz', the result is 'baz'.

        My version returns 3.

        Now the question is why?

        Why preserve or emulate the list-in-a-scalar-context semantics?

        Is there ever a situation when arbitrarially returning the last physical value in a list is the right thing to do?

        And if anyone knows of such an occasion, does this occur so frequently that it is worth while imposing the additional costs on every other use of the sub in order to avoid the need to do

        my $last = ( foo() )[ -1 ];

        which would be hugely clearer as to the desired result than my $last = foo(); as well as considerably more efficient for the general case.

        I've always considered this side-effect of a list in a scalar context to be terminally broken and something that really ought to be fixed. The argument against fixing it is probably backwards compatibility, but I would argue that given the rarity that this behaviour is likely to be used and depended upon by real code, and that it is so easy to achieve the equivalent with a simple modification that increases the clarity of the desired result so much, that it would be better for everyone to force the fix upon existing code that relies upon this behaviour.

        I find the idea of coding a sub in such a convoluted manner in order to perpetuate this broken behaviour an anathema.


        Examine what is said, not who speaks.
        "Efficiency is intelligent laziness." -David Dunham
        "Think for yourself!" - Abigail
        Hooray!
        Wanted!