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;
>     }

Reply via email to