The short version: state and foreach do not mix. The same bug also makes my $a; eval'\$a=\$b' do nothing. (I am working on lvalue references right now.) Is it acceptable to introduce experimental lvalue references with that drawback? The rest of the message discusses ways to fix the bug. The long version: use 5.01; sub f { state $x; $x = 42 if !caller(1); if (!@_) { return } my $what = shift; if ($what eq 'print x2') { # print $x under recursion (depth=2) f('print x'); } elsif ($what eq 'print x') { print "$x\n"; } elsif ($what eq 'alias') { foreach $x (100) { f(); } } } #f('print x2'); f('alias'); f('print x2'); This script outputs 100, because in the 2nd call depth $x is perma- nently bound to the 100 constant that it was temporarily aliased to by the foreach loop in the first f() call. If we uncomment the line that is commented out, we get 42 twice. This is because $x is now correctly shared between the two depths. This exposes a bug in the way that closures are handled. (This exam- ple is not a closure example, but closure would exhibit the same bug as the principle is the same: multiple pads point to the same SV, but aliasing only affects one pad at a time.) One way to fix this would be to put RVs in pads instead of putting values in the pads directly. While I don't think it would slow things down considerably, the slowdown would probably be measurable, and I would have a lynch mob after me. (Slowing down lexical variables is sacrilege. :-) Another approach I thought of was to store a generation number some- where (e.g., the pad name) and have padxv ops that are flagged as closing over outer subs fetch the new value if the current value is stale. But storing the generation number in the pad name is compli- cated, as I made CV clones share pad names about two years ago, for efficiency. And then it is complicated to find the outer sub, as clo- sures no longer point to it as of about two years ago, again, for efficiency. (So much for efficiency!) So I'm not sure how to proceed. Maybe we just need to use RVs (and actually benchmark them to see how much slowdown we get). Maybe we should only use RVs if the current sub or an inner sub contains evals. (Getting that to work would be hard.) Maybe we need a lightweight reference-counted SV pointer, which we would call a PADSLOT, since the SV head is 8-12 bytes bigger than we need. But I loathe breaking all the CPAN modules that handle pads directly via PadARRAY. (The whole point of the new pad API was to avoid future breakage.) I would appreciate any bright ideas. If we can't fix this now, is it acceptable to introduced experimen- tal lvalue references with this drawback? my $a; eval { \$a = \$b } would be ineffective, as the aliasing would only take place in the eval's own pad.Thread Next