Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer
 
PerlMonks  

Re: regexp list return 5.6 vs 5.8

by Sixtease (Friar)
on Jan 24, 2008 at 09:42 UTC ( #663971=note: print w/replies, xml ) Need Help??


in reply to regexp list return 5.6 vs 5.8

Is the behavior of list slice subroutine return an intended feature

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?

sub is_digits { my @rv = $_[0] =~ /^([0-9]+)$/; return @rv[ 0 .. $#rv ]; } my $nothing = is_digits('abc'); my @arr1 = ($nothing); my @arr2 = ('some', 'thing'); push @arr2, @arr1; print "There are ", scalar(@arr2), " elements in \@arr2\n"; print '$arr2[2] is ', defined($arr2[2])?'':'un', "defined\n";

What I expect and get on 5.8.8 is:

There are 3 elements in @arr2 $arr2[2] is undefined

Update: Modified the code to more closely follow the original.

use strict; use warnings; print "Just Another Perl Hacker\n";

Replies are listed 'Best First'.
Re^2: regexp list return 5.6 vs 5.8
by shmem (Chancellor) on Jan 24, 2008 at 11:13 UTC
    A slice is not an array. What you return is what you get.

    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:

    perl -le 'sub x {@x = qw(a b c); @x }; $r=x; print $r' 3 perl -le 'sub x {@x = qw(a b c); ()=@x }; $r=x; print $r' 3 perl -le 'sub x {@x = qw(a b c); @x[0..$#x] }; $r=x; print $r' c perl -le 'sub x {@x = qw(a b c); ()=@x[0..$#x] }; $r=x; print $r' 3

    Any formal explanation why the third and fourth of these (should) yield different output?

    Last but not least - allowing a more relaxed coding style in test scripts: IMHO that is the place where most robust code is required: flawed tests are useless.

    --shmem

    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}

      Very good points. I'll try to be more disciplined with test.

      What about this one:

      perl -le 'sub x { return qw(a b c);}; $r=x; print $r' c

      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
      use strict; use warnings; print "Just Another Perl Hacker\n";
        It is stated in perldata - in parens!
        Assignment is a little bit special in that it uses its left argument to determine the context for the right argument. Assignment to a scalar evaluates the right-hand side in scalar context, while assignment to an array or hash evaluates the righthand side in list context. Assignment to a list (or slice, which is just a list anyway) also evaluates the righthand side in list context.

        Then there's perlop which states that qw generates a real list at compile time, and returns the last element of that in scalar context (which AFAIK is resolved at runtime). Array slices seem to work the same way (compile time list construction).

        But that either

        • shouldn't be the case with subroutine returns, according to the docs, or
        • should be documented in the docs, like, "Subroutines return lists, except when they don't. Aggregates are returned as flattened lists, but lists are evaluated in the caller's context".

        Subroutine return values are evaluated in the caller's context on return, they are not made into a list context on exit which is then evaluated in the caller's context. This is arguably a feature...

        Thanks for bringing that up.

        --shmem

        _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                      /\_¯/(q    /
        ----------------------------  \__(m.====·.(_("always off the crowd"))."·
        ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}

        Works for me on both ancient versions of perl;-)

      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)

      Something that just crossed my mind and turned out to behave like I didn't expect:

      perl -le 'sub x { my @x = qw(a b c); my @y = qw(A B C D); return (@x, +@y)} my $r = x(); print $r' 4

      Must say it made me LOL :-)

      use strict; use warnings; print "Just Another Perl Hacker\n";
        From what we've already discussed I would have expected the outcome:
        • the return list is constructed at compile time.
        • at runtime, the list (@x, @y) is evaluated in the caller's context, so it resolves to the comma operator, returning it's last argument - @y
        • then the array @y is evaluated in the caller's context, which happens to be scalar, hence 4 as a result.

        Pretty much the same as

        perl -le '@x=qw(a b c);@y=qw(a b c d); $f=(@x,@y); print $f' 4

        ;-)

        --shmem

        _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                      /\_¯/(q    /
        ----------------------------  \__(m.====·.(_("always off the crowd"))."·
        ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
      You're right about the behavior of slices, but it has nothing to do with subroutine returns. See for example:
      perl -e"my @a=qw/a b c/; print scalar @a[0..2]" c
      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.
Re^2: regexp list return 5.6 vs 5.8
by hipowls (Curate) on Jan 24, 2008 at 10:34 UTC

    On Solaris 5.6.1 I got

    michaela@drvdb2:michaela$ perl s.pl There are 3 elements in @arr2 $arr2[2] is undefined

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others cooling their heels in the Monastery: (5)
As of 2020-10-20 06:19 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    My favourite web site is:












    Results (209 votes). Check out past polls.

    Notices?