Padre is using Actions for menu options, shortcuts, etc. The Action for showing the Perl help search (F2) is handled by the following piece of source:
Once I verified that each F2 keypress reached this point by adding a debug print above the loop, the following debug prints got surprising results:for ( @{ $self->{event} } ) { next if ref($_) ne 'CODE'; &{$_}(@args); }
This may trigger a "Use of uninitlized value" warning as "use warnings;" is active, but I don't care of them for debug prints which never reach the public. Anyway, here is the result:print "---START---\n"; for ( @{ $self->{event} } ) { print STDERR $self->{name}." => $_\n"; next if ref($_) ne 'CODE'; &{$_}(@args); }
We're walking through an array which isn't - believe me - touched anywhere, but the first value magically changes. Memory corruption? Human computer? Moon phase problems? No! It's the $_'s evil side. The fix was simple:---START--- help.search => CODE(0x9bcb9b0) help.search => CODE(0xa2f8618) ---START--- help.search => -f help.search => CODE(0xa2f8618)
Here we go:print "---START---\n"; for my $item ( @{ $self->{event} } ) { print STDERR $self->{name}." => $item\n"; next if ref($item) ne 'CODE'; &{$item}(@args); }
What happend?---START--- help.search => CODE(0x9bcb9b0) help.search => CODE(0xa2f8618) ---START--- help.search => CODE(0x9bcb9b0) help.search => CODE(0xa2f8618)
$_ was used by the loop, but it was no copy of the first array item, it was referencing it. Because something in the called CODE(0x9bcb9b0) was using $_, the new value was stored into the referenced place - the first array item overriding it's own CODE-reference.
By using a private (my) variable for the loop, $_ isn't used any longer and the problem was gone: http://padre.perlide.org/trac/changeset/8727/trunk/Padre/lib/Padre/Action.pm
This is a common problem which triggers Perl newbies and experts and which is usually hard to find, because the errors occurs at a place somewhere later when using the modified data, but if you respect this rule, you should be safe:
Use a private my-variable for looping whenever you call a sub or method within your loop!
In reply to Magical data modification using $_ by Sewi
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |