Coderef to object methods?

R

robb

Hi,

I found examples of coderefs to subroutines in Perl Objects, References
and Modules, chapter 6. It goes something like this:

# Assignment
$subroutine_ref = \&subroutine;

# Invocation
$subroutine_ref->( ... );

But what I need is to obtain a reference to an instance method in the
class in which I'm coding. Anybody know what the syntax would look
like?

Thanks,
Robb
 
X

xhoster

Hi,

I found examples of coderefs to subroutines in Perl Objects, References
and Modules, chapter 6. It goes something like this:

# Assignment
$subroutine_ref = \&subroutine;

# Invocation
$subroutine_ref->( ... );

But what I need is to obtain a reference to an instance method in the
class in which I'm coding. Anybody know what the syntax would look
like?

If you are in the class which you are coding, then the method is just
a subroutine, so you take a reference to it the same way you take a
reference to a subroutine.

Otherwise, if you want the object on which to opperate to be enclosed in
the coderef, then maybe a closure is what you want?

my $closure = sub {$object->method(@_)};

Xho
 
P

Paul Lalli

I found examples of coderefs to subroutines in Perl Objects, References
and Modules, chapter 6. It goes something like this:

# Assignment
$subroutine_ref = \&subroutine;

# Invocation
$subroutine_ref->( ... );

But what I need is to obtain a reference to an instance method in the
class in which I'm coding. Anybody know what the syntax would look
like?

What we think of as "object method calls" are really just subroutine
calls with a bit of misdirection and another bit of magic thrown in.
If you have an object $obj of the class MyClass, then saying:
$obj->foo('bar');
is actually translated by Perl into:
MyClass::foo($obj, $bar);

(The "magic" component is inheritance. The arrow notation will
automatically search $obj's inheritance tree for foo() if it can't find
one in MyClass. The standard notation will not)

So if you want a reference to a method, and to be able to call it from
any object, it's pretty straightforward:

my $meth_ref = \&MyClass::foo;
$meth_ref->($obj, $bar);

If, however, you want to be able to store a reference to a method of a
specific given object, it's a little more complicated. As far as I can
remember, you have to use a closure....
[untested]
my $obj_meth_ref = $obj->make_meth_ref();
$obj_meth_ref->('bar');
#within MyClass.pm now...
sub make_meth_ref {
my $obj = shift;
return sub {
$obj->foo(@_);
};
}


Hope this helps point you in the right direction, at least...

Paul Lalli
 
R

robb

If you are in the class which you are coding, then the method is just
a subroutine, so you take a reference to it the same way you take a
reference to a subroutine.

Otherwise, if you want the object on which to opperate to be enclosed in
the coderef, then maybe a closure is what you want?

Thanks for the reply. I'm not sure if I need a closure. I'm mapping a
list of strings to private methods that I want to invoke. I'd like to
have syntax like this be valid:

# Assignment
my %method_map = ('feature1' => \&_a_private_method);

# Invocation
my $method_ref= $method_map{'feature1'};
$self->$method_ref( $parameter );

Is there some syntax that's close to this that'd work?
 
R

robb

Paul said:
So if you want a reference to a method, and to be able to call it from
any object, it's pretty straightforward:

my $meth_ref = \&MyClass::foo;
$meth_ref->($obj, $bar);

Thanks for the detailed reply. And this example will probably work for
me.

Now, though, I have to decide whether to go this route at all.
Currently, I'm using the method name to do this mapping:

my $method_name = $method_map{$some_user_input};
return $self->$method_name($data);

I looks a little more straightforward to me, than going the coderef way.
 
X

xhoster

Thanks for the reply. I'm not sure if I need a closure. I'm mapping a
list of strings to private methods that I want to invoke. I'd like to
have syntax like this be valid:

# Assignment
my %method_map = ('feature1' => \&_a_private_method);

# Invocation
my $method_ref= $method_map{'feature1'};
$self->$method_ref( $parameter );

Is there some syntax that's close to this that'd work?

You can use an ordinary string with the name of the method,
or the UNIVERSAL::can method, or just just take a reference to
fully qualified sub.

perl -wle 'package foo; sub bar {print "asfdadsf"}; package main; \
$bar="bar";foo->$bar();'

perl -wle 'package foo; sub bar {print "asfdadsf"}; package main; \
$bar=foo->can("bar");foo->$bar();'

perl -wle 'package foo; sub bar {print "asfdadsf"}; package main; \
$bar=\&foo::bar;foo->$bar();'

Xho
 
B

Brian McCauley

Thanks for the reply. I'm not sure if I need a closure. I'm mapping a
list of strings to private methods that I want to invoke. I'd like to
have syntax like this be valid:

# Assignment
my %method_map = ('feature1' => \&_a_private_method);

# Invocation
my $method_ref= $method_map{'feature1'};
$self->$method_ref( $parameter );

Is there some syntax that's close to this that'd work?

Er, that exact syntax will work. But method-refs in Perl are only fully
supported as symbolic refs. This is because Perl5's implementation of
object inheritance relies on doing method lookups at runtime using
strings.

If $method_ref is a hard coderef then:

$self->$method_ref( $parameter )

is more or less just another way of saying

$method_ref->( $self, $parameter )
 
R

robb

Brian said:
Er, that exact syntax will work. But method-refs in Perl are only fully
supported as symbolic refs. This is because Perl5's implementation of
object inheritance relies on doing method lookups at runtime using
strings.

Excellent. So it sounds like I can use this simple syntax, at the
price of not having inheritance supported?

That'd work for me - I'm not using inheritance.

The only problem would be if perl expects inheritance to function -
ie., if there's an implicit parent Object class with important built-in
functionality. (ala Smalltak, Python, Java...) It sounds like this
isn't the case. (?)
 
A

anno4000

You can use an ordinary string with the name of the method,
or the UNIVERSAL::can method, or just just take a reference to
fully qualified sub.

A nice list.

The alternatives differ in when (or if) method lookup through classes
takes place.
perl -wle 'package foo; sub bar {print "asfdadsf"}; package main; \
$bar="bar";foo->$bar();'

Here method lookup happens on every call, just like in "foo->bar()".
perl -wle 'package foo; sub bar {print "asfdadsf"}; package main; \
$bar=foo->can("bar");foo->$bar();'

Here ->can does a method lookup. The result is frozen into the
coderef $bar. There is no method lookup at call time.
perl -wle 'package foo; sub bar {print "asfdadsf"}; package main; \
$bar=\&foo::bar;foo->$bar();'

No method lookup happens at all. $bar becomes a coderef to the sub
bar() in package "foo", no two ways.

Anno
 

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

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,535
Members
45,007
Latest member
OrderFitnessKetoCapsules

Latest Threads

Top