>>>>> "GB" == Graham Barr <gbarr@pobox.com> writes: GB> On Sun, Jan 07, 2001 at 08:56:32PM +0000, Ton Hospel wrote: >> In article <20010107175242.A1935@pembro26.pmb.ox.ac.uk>, >> Simon Cozens <simon@cozens.net> writes: >> > On Sun, Jan 07, 2001 at 12:30:06PM -0500, Ronald J Kimball wrote: SC> sub foo :lvalue {shift} foo($a) = 7 TH> You are returning a COPY of the value of the first parameter. TH> shift does not give an lvalue GB> That is not completely true. GB> sub abc { return \shift } GB> $a = 1; GB> $b = abc($a); GB> warn $$b; GB> ${$b}++; GB> warn $a; Right. shift() isn't syntactically an lvalue (i.e., in the sense of mod()), but it really does return the actual first element of the array, not a copy. An example that doesn't use a subroutine: perl -e '@x=(1); $r = \$x[0]; ${\shift(@x)}++; print "$$r\n"' 2 The fact that you aren't allowed to assign directly to shift() makes it hard to tell that it isn't a copy (you get a copy if you say `$x = shift(@x); $x++'), but references give a way to peek at the real SV. Shifting @_ is different from shifting other arrays in that @_ doesn't normally hold reference counts for its elements (since it's just the stack), so the result of shifting @_ doesn't have to be mortal-ized. Another brainteaser along these lines is perl -e 'sub f :lvalue {@x=(1); $r = \$x[0]; (shift @x, $$r)[1]}; f() = 5' I'd challenge anyone to defend why that croaks but perl -e 'sub f :lvalue {@x=(1); $r = \$x[0]; shift @x; $$r}; f() = 5' doesn't complain. (The explanation of why it doesn't work is that since the $$r is in the same statement as the shift, the SV it refers to is still mortal, and you can't lvalue return mortals; but I can't defend that, it seems like a bug). -- Stephen McCThread Previous | Thread Next