Object reference vanishes from $_[0]

From: Kanenas (kanenas_at_comcast.net)
Date: 02/13/05


Date: 12 Feb 2005 15:49:42 -0800

So I'm playing around with overloading the code dereference operator
(referred to as '&{}' in the overload package documentation) so that I
can make any object callable when I run into a problem with goto &NAME.
 To get '&$obj' to call a method of $obj, I have '&{}' wrap the method
in an anonymous sub which prepends a reference to the object to @_ (see
code below). Thus I can use the goto &NAME form of goto in the
anonymous sub and it's as if '$obj->(@args)' was actually a call to the
method. That works just fine for my purposes (it will only call the
method of the base class, not an overriden method in any derived class,
but I have other ways of addressing that), but if the method also uses
goto &$code where $code is a code ref , the object reference vanishes
from @_ UNLESS I alter @_ via push, pop, shift, unshift or slice
(assigning to an element of @_ doesn't work and is bad because elements
of @_ are aliased to the actual arguments of the '$obj->(...)' call).
I get this behavior under Perl 5.8.5 on OpenBSD 3.6 and ActivePerl
5.8.4 on Win98. What is happening?

It doesn't matter at all for the example below, as the goto in 'bar' is
completely superfluous, but sometimes I'd like to be able to goto
methods stored within the object. I could, for those specific
instances, have the anonymous sub returned by '&{}' goto the method
stored within the object, but (as noted above) I'm working on a more
general solution to make objects callable. The gotos are needed in
case the method uses caller(), which should refer to whatever called
&$obj, not any wrappers.

Here's some code that illustrates the issue (but not so much why you'd
want to do what I want to do).
<code>
#! /usr/bin/perl

package Foo;
use overload '""' => sub {$_[0]},
  '&{}' => sub {
    my $self = shift;
    return sub {unshift @_, $self; goto &bar}
  };

sub new { return bless {}, shift; }
sub bar {
  push @_, '';
  pop;
  print "Foo::bar(",join(', ', @_),")\n";
  goto &baz;
}
sub baz { print " ", ref $_[0],"->baz(",join(', ', @_),")\n" };

package main;

$foo = Foo->new();
$foo->bar('direct');
$foo->('code deref');
</code>

With the push & pop in Foo::bar you get:
    Foo::bar(Foo=HASH(0x155f9b4), direct)
      Foo->baz(Foo=HASH(0x155f9b4), direct)
    Foo::bar(Foo=HASH(0x155f9b4), code deref)
      Foo->baz(Foo=HASH(0x155f9b4), code deref)

which is fine and dandy. If you comment the push & pop in Foo::bar you
get:
    Foo::bar(Foo=HASH(0x155f9b4), direct)
      Foo->baz(Foo=HASH(0x155f9b4), direct)
    Foo::bar(Foo=HASH(0x155f9b4), code deref)
      ->baz(, code deref)

Note $foo->{callee} no longer gets a reference to $foo when called via
overloaded '&{}'. The successive 'gotos' are not the problem, as
adding 'sub foo {goto &bar}' to Foo and calling '$foo->foo()' works
fine.

I hope what I want to do makes sense even if why doesn't. I fear
including too much of "why" will make the issue less clear, so I
discarded some "why" and made the simplest "what" I could with the
above example code.

A simpler question: does anyone know of a package in CPAN which can
make arbitrary objects callable? I couldn't find one, but wasn't
coming up with good search terms. Package overload does a little in
this regard, but there are some hoops to jump through so that methods
(and callable objects) are called properly, hoops I am trying to hide
within another package.



Relevant Pages

  • Re: Beginner - ETX 90AT vs. EC
    ... ETX90 AT was my first half decent scope since childhood. ... Without the GoTo, it was very hard to use indeed. ... > those messages claimed that the EC package is the same as the AT ...
    (sci.astro.amateur)
  • Re: goto &Package::func destroying @_?!
    ... >>script, but maybe the description will trigger something from someone.... ... code the 'Core' package uses another package as a base that has a custom ... package Foo; ... if it really is a problem with goto&. ...
    (comp.lang.perl.misc)
  • Re: VHDL-like fixed-point in Verilog?
    ... assignment in VHDL really comes back to bite us here. ... package, I "solved" this by creating a copy procedure ... Since resize() has a version where you pass it the target argument ... I wonder if it would be better to overload all the operators to return ...
    (comp.lang.verilog)
  • Re: Skip DTS steps
    ... www.SQLDTS.com - The site for all your DTS needs. ... > GOTO "STEP XXXX" ... > Where "STEP YYYY" and "STEP XXXX" would be the steps of the package that I ... > it to report an error back. ...
    (microsoft.public.sqlserver.dts)
  • Attributes and Overload in XS
    ... how the pragma "use overload ..." ... For example, if "+" was overloaded in a particular package, ... MTIA for your answers, and kind greetings from Vienna, ...
    (comp.lang.perl.misc)