On 02/12/04 21:03 -0600, Steve Peters wrote:
> On Thu, Dec 02, 2004 at 06:04:11PM -0800, Brian Ingerson wrote:
> > ...
> > Is there a fast fix to this, or should I start looking for a workaround?
>
> OK, I added a few print statements to clear thing up for me somewhat.
> The code still is a bit mirky to me, since I honestly have no clue how
> DB::args is getting populated (someone please explain, if you can).
> Anyways, foo() seems to be the sticking point. Changing @_ to @foo and
> passing it to bar rather than doing a goto seems to work. I've tried
> on 5.8.0, 5.8.5, and 5.8.6 with identical results.
>
> As for the actual cause, it is likely related to how @DB::args is
> getting populated, but since I don't know how that is happening, I
> can't be much more help for you.
Steve, Thanks for looking into this. Hopefully I can clarify the
situation a bit. First a small intro to what broke:
Spiffy::super() provides a way to turn this idiom
sub foo {
my $self = shift;
$self->SUPER::foo(@_) . $self->other_stuff;
}
Into:
sub foo {
super . $self->other_stuff;
}
Actually, Spiffy adds 'my $self = shift' to all the subroutines, and
exports a function called super.
super() uses caller() and the @DB::args trick to figure out context
and arguments, and then uses goto() to get to the right place. I got
the idea for super() and using @DB::args from Simon Cozen's SUPER.pm.
(I included this as one of the really nice things that Spiffy does to
make OO programming cleaner. Spiffy even takes it a little farther and
allows you to call super() from AUTOLOAD, which you couldn't do with the
old SUPER.)
Simon got the idea from the 'perlfunc' manpage. To quote:
Furthermore, when called from within the DB package, caller returns
more detailed information: it sets the list variable @DB::args to be
the arguments with which the subroutine was invoked.
Basically this is a documented, albeit kludgy extension to the caller()
function. And it breaks in 5.8.6. See t/autoload.t and t/super2.t in the
Spiffy dist.
Actually super() works the first time you call it, but not the second
time, because by that time goto was called (by the previous super).
I hope this helps you figure out what's going on. If you want me to
write a failing test for the core, I'd be happy to. Just let me know.
Cheers, Brian
As for the code below, there are still many combinations of things that
work with @DB::args, but alas none that I have found to allow me to work
around what broke in 5.8.6.
> use Data::Dumper;
>
> foo(1..3);
>
> sub foo {
> @foo = (4..6);
> bar(@foo);
> }
>
> sub bar {
> print join qw/ : /, @_; print "\n";
> shift;
> print join qw/ : /, @_; print "\n";
>
> print Data::Dumper::Dumper(DB::get_args(1));
> }
>
> package DB;
> print @args;
> sub get_args {
> print join qw/ : /, @_; print "\n";
> my @dummy = caller(shift);
> print join qw/ : /, @dummy; print "\n";
> @DB::args;
> print join qw/ : /, @DB::args; print "\n";
> return @DB::args;
> }