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

Hello everybody,

Please, can there be a difference between what the following snippet would return on perl5.8 and perl5.6? I'm getting test failures from cpan testers (God bless them) on perl5.6, where it seems to return 1 where $_[0] has no digits.

i don't have access to 5.6 at the moment and so cannot investigate your question, but just as a matter of curiosity, why use the expression return @rv[ 0 .. $#rv ]; when it seems to me it will return exactly the same thing as return @rv; and when the latter expression does not involve the behavior of the .. range operator in the case where the terminal value is less than the initial value, i.e., 0 .. -1 in the case of $#rv when the array @rv is empty?

Is the behavior of list slice subroutine return an intended feature, is it specced somewhere (or even documented)? Or is it just an implementation detail which might some day be considered a bug and be changed thereafter?

michael$ perl t.pl
[[]
[]
[123]
[123]
michael:$ perl -v
This is perl, v5.6.1 built for sun4-solaris
Copyright 1987-2001, Larry Wall
Perl may be copied only under the terms of either the Artistic License+ or the
GNU General Public License, which may be found in the Perl 5 source ki+t.
Complete documentation for Perl, including FAQ lists, should be found +on
this system using `man perl' or `perldoc perl'. If you have access to+ the
Internet, point your browser at http://www.perl.com/, the Perl Home Pa+ge.

michael$ /usr/local/bin/perl t.pl
[[]
[]
[123]
[123]
michael$ /usr/local/bin/perl -v
This is perl, version 5.005_03 built for sun4-solaris
Copyright 1987-1999, Larry Wall
Perl may be copied only under the terms of either the Artistic License+ or the
GNU General Public License, which may be found in the Perl 5.0 source +kit.
Complete documentation for Perl, including FAQ lists, should be found +on
this system using `man perl' or `perldoc perl'. If you have access to+ the
Internet, point your browser at http://www.perl.com/, the Perl Home Pa+ge.

A slice is not an array. What you return is what you get. I don't see any magic there. You're definitely right about not golfing production code. This is from a test script however - I allow myself a little more relaxed way of coding in those. :-)

I think I understand the thing now - it's an XY case if I'm correct. That subroutine's return value has been assigned to a scalar and that has been pushed to an array. Maybe this code works differently on 5.6?

Indeed, but that distinction isn't defined for subroutine return. From perlsub:

The Perl model for function call and return values is simple: all
functions are passed as parameters one single flat list of scalars,
and all functions likewise return to their caller one single flat
list of scalars. Any arrays or hashes in these call and return
lists will collapse, losing their identities--but you may always
use pass-by-reference instead to avoid this. Both call and return
lists may contain as many or as few scalar elements as you'd like.
(Often a function without an explicit return statement is called a
subroutine, but there's really no difference from Perl's perspective.)

...

A "return" statement may be used to exit a subroutine, optionally
specifying the returned value, which will be evaluated in the
appropriate context (list, scalar, or void) depending on the context
of the subroutine call. If you specify no return value, the
subroutine returns an empty list in list context, the undefined
value in scalar context, or nothing in void context. If you return
one or more aggregates (arrays and hashes), these will be flattened
together into one large indistinguishable list.

Subroutines return a list of scalars - that's it. Nothing is said about how
flattening of aggregates is done, nor is any distinction made between
arrays and plain lists.

I'd not see that as a language feature (muss less a desired one),
but as a dark corner which should be inspected for sanity. All of the following
snippets should behave the same way:

This returns the plain list and that's what I want to mimic having it in an array. Arrays and list assignments have special meanings in scalar context. Slices do not. I don't know excactly where but it is documented. (I mean, it's documented that arrays and list assignments have the special scalar-context behavior, not that slices don't :-))

Update: From perldata:

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

List assignment in scalar context returns the number of elements produced by the expression on the right side of the assignment:

And, as you quoted from perlsub:

A "return" statement may be used to exit a subroutine, optionally specifying the returned value, which will be evaluated in the appropriate context

The issue is that an array (or hash, or list) slice in scalar context returns the last element of the slice. I feel like this should be documented in perldata but a quick read of it just now didn't reveal any such indication.

Subroutines return a list of scalars, but when the sub is in scalar context, that list will always have exactly one scalar in it.

"A 'return' statement [...] will be evaluated in the appropriate context" means the op which returns the arguments to return is executed in the same context as the sub. It's the *statement* that is evaluated in the appropriate context, not the values returned.

When evaluated in scalar context, arrays return their length. (Case 1)
When evaluated in scalar context, lists return their last element. (Case 3)
When evaluated in scalar context, list assignments return the number of elements assigned. (Case 2 and 4)

I'm still very curious about the weird [[] and {{} that hipowls was getting. Maybe it's worth a thread.

It would seem that I'm unable to locate the cause of the error people seem to experience testing my package on v5.6. If any of you are interested, it's Data::FeatureFactory on cpan, maybe you can have a look (make test). I'll try to find a 5.6 installation somewhere and play with it.

I get the same behaviour with 5.8.4, BTW. It seems that when the range 0..-1 is
used to select the elements of the slice ($#rv is -1 when @rv is
empty), the 'final element' of the slice (incorrectly) evaluates to the previous/last
element on the Perl stack (or some such). With Perl versions up to at
least 5.8.4, that is — but no longer with 5.8.8 and 5.10.0 (I currently
don't have access to versions 5.8.5 - 5.8.7, so I can't tell when it got fixed).

(Ranges like [99..98] behave the same way as [0..-1], so
what seems to matter is just that the second value in the range is
smaller than the first...)

-------------------
Use of uninitialized value in print at ./663945.pl line 9.
[foo]
-------------------
[fooB]
-------------------
[fooA]
-------------------
Use of uninitialized value in print at ./663945.pl line 15.
[foo]
-------------------

As has already been pointed out elsewhere in the thread, this is
mostly expected behaviour, because (from perldoc -f scalar)

scalar EXPR
(...)
Because "scalar" is unary operator, if you accidentally use for EXPR
a parenthesized list, this behaves as a scalar comma expression,
evaluating all but the last element in void context and returning the
final element evaluated in scalar context.

...except for the "[foo[foo]", of course.

I don't have a real explanation (probably simply a bug)...
just a couple of related observations with respect to using [0..-1] with
slices. When you use a literal list instead of a named array, there's
still some curious behaviour in recent releases of Perl:

OK, one more question: How do you guys recommend that I flatten lists? I mean... say I have some values in an array, or in two arrays and I want to turn it into one flat list that will not have any array-specific or similar behavior. I can want to pass it from a subroutine, from a do statement or from a map block or eval or whatever...

Update: How about map $_, @stuff, @more_stuff?

Update 2: Nope. As documented: "In scalar context, returns the total number of elements so generated."

What do you mean exactly? What kind of "array-specific" behavior are you trying to avoid? If you want to take data you are creating as a list but apply it in scalar context, you need to make some decision for yourself about what data you want and code accordingly. For example, map operates on a list and returns a list. If you want to use that in scalar context, and want something other than the length of the list as the value, you need to decide what you want. If you always want the last value, one way to do that is

OK, one more question: How do you guys recommend that I flatten lists? I mean... say I have some values in an array, or in two arrays and I want to turn it into one flat list that will not have any array-specific or similar behavior.

but less ugly, and without having to take special care of the
subtle problem you run into with older versions of Perl when the
arrays are empty, and the selecting range for the slice becomes
[0..-1] (what this thread is about, essentially).

Irrespective of whether you'd actually need to do something like
this in real-life programming, it's still a valid question in and of
itself, IMO.

I think whether you get different behaviour depends on the exact circumstances in which the evaluation happens. I would argue that you don't see a difference, because there's
nothing "on the stack" (as I hypothesized in my other reply) prior to the evaluation of the slice in scalar
context. If I modify your test slightly, I do get different results
depending on Perl version.

5.8.4 prints foo (and no warning), while 5.8.8 and 5.10.0 print
Use of uninitialized value $s in print at -e line 1. (and no "foo").

Note 1: the sub {"foo"}->() is just a way to
avoid the "Useless use of a constant in void context",
which I would otherwise get when simply writing "foo", ...

Note 2: Windows users will probably have to swap single and double
quotes (I changed them myself in the first place, because
ikegami's original version would have required additional quoting
with a typical Unix shell...)

When putting a smiley right before a closing parenthesis, do you:

Use two parentheses: (Like this: :) )
Use one parenthesis: (Like this: :)
Reverse direction of the smiley: (Like this: (: )
Use angle/square brackets instead of parentheses
Use C-style commenting to set the smiley off from the closing parenthesis
Make the smiley a dunce: (:>
I disapprove of emoticons
Other