Object reference vanishes from $_[0]

K

Kanenas

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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top