Ok, I can sort of see what's going on here. the scope with the regex
is left, and @+ gets restored to it's old value (empty). So my result
still knows it was 2 long, but the values are gone, and I get 2 undefs.
But why didn't I get copies of the values, no longer sensitive to
their origin evaporating ?
If I try to sort of do this (as much as possible) with a normal array,
I don't observe the effect:
perl -wle 'sub DESTROY { $a[0]=1} @a="a".."c"; sub f { my $a=bless[]; return @a } print f'
abc
(I was sort of starting to expect 1bc here)
Is this weird combination of the new size with the old values what I
should have expected ?
perl -wle '"xyz"=~/(.)(.)/; print "@+"; sub f {"ab" =~ /(.)/; print "@+"; return @+} print f'
2 1 2
1 1
21
I think that this behaviour of @+ et alii is similar to the automatic
scoping of $1 et alii.
It's not the scoping that surprises me, that is expected.
What surprised me is that the return value isn't a copy.
Notice that this works as expected,
even though $1 also goes out of scope:
perl -wle 'sub f {"ab" =~ /(.)/; return $1}; print f'
Ooh, that's a bug. A strange one, a cursory inspection of the sources
makes me think that it *should* work -- the values ought to be copied,
like when you return explicitly ($+[0],$+[1]).
Looking at the difference between pp_rv2av() and pp_aelemfast(), which
causes the difference in behaviour between C< @+ > and C< ($+[0], $+[1]) >,
the patch below may be desirable. But I really don't understand the
ramifications of it well enough to know whether it should go in.
Without this, the things put on the stack for C< return @+ > are the
magic lvals constructed in av_fetch().
No tests failed for me with this; I wonder whether it would cause problems
for anyone making heavy use of ties or other magic on arrays.
Of course if it turns out that everyone calling av_fetch(av, key, FALSE)
should be doing this, it would probably be better for av_fetch() to be
doing it itself - it can certainly do so much more efficiently. That would
probably imply spliting out an av_fetch_rval() for internal use, to avoid
breaking existing usage.
And we should probably look at pp_rv2hv in case that needs something similar.
Hugo
--- pp_hot.c.old Wed Feb 25 01:55:25 2004
+++ pp_hot.c Fri Mar 5 17:33:26 2004
@@ -778,7 +778,10 @@
U32 i;
for (i=0; i < (U32)maxarg; i++) {
SV **svp = av_fetch(av, i, FALSE);
- SP[i+1] = (svp) ? *svp : &PL_sv_undef;
+ SP[i+1] = (svp)
+ /* see note in pp_helem, and bugid ?? */
+ ? SvGMAGICAL(*svp) ? sv_mortalcopy(*svp) : *svp
+ : &PL_sv_undef;
}
}
else {