Remember
::* and
->* from C++? If you do, you probably hate them.
A pointer to a member function lets you store a particular method in a variable and then apply it to objects. Here's how to get them in Perl.
It's a bit long, but almost all of it isn't code...
# Perl "pointer to member function" abstraction
package PMF;
use strict;
use Carp;
sub new {
my ($class,$name) = @_;
$name =~ /^[A-Za-z0-9_]\w*$/ or croak "Bad method name \"$name\"";
bless eval <<"END_CODE", $class;
sub {
my \$self = shift;
\$self->$name(\@_)
}
END_CODE
}
sub call {
my $self = shift;
$self->(@_)
}
package PMF::able;
sub call { # permute our args
my $self = shift;
my $pmf = shift;
$pmf->($self,@_);
}
=head1 NAME
PMF - pointer to member function in Perl
=head1 SYNOPSIS
my $p = PMF->new('print');
my $x = ClassWithPrintMethod->new(17);
$p->($x, 'foo'); # call $x->print('foo')
$p->call($x, 'foo'); # call $x->print('foo') in another way
package MyClass;
use vars qw/@ISA/;
@ISA = qw/PMF::able/;
# ...
package main;
my $y = MyClass->new('xyz');
$y->call($p, 42); # call $y->print(42)
=head1 DESCRIPTION
C<PMF> gives you pointers to member functions. A PMF is the
abstraction of calling a particular method of an object, similar to
the C<::*> / C<-E<gt>*> mess of C++.
To create a PMF, pass C<new> the name of the method you want to
call. C<PMF::new> creates a code object that calls that method of any
object (contrast C++ pointers to member functions, which are
restricted to subclasses of some root class). Lacking a better
dispatch syntax, you apply a PMF C<$pmf> to an object C<$obj> by
saying C<$pmf-E<gt>($obj, I<args...>)>.
=head1 ALTERNATE CALLING SYNTAX
If you would rather say C<$obj-E<gt>call($pmf, I<args...>)>, you need
to make the class of C<$obj> inherit from the mixin class
C<PMF::able>, which provides exactly this C<call> method.
If you wish to avoid changing the class of C<$obj>, you can still use
the alternate syntax by creating your objects in an appropriate dummy
class:
package MyClass2;
use vars qw/@ISA/;
@ISA = qw/ClassWithPrintMethod PMF::able/;
# empty package body!
package main;
my $z = MyClass2->new(19);
$z->call($p, 'foo');
=head1 NOTES / BUGS
=over 4
=item *
A PMF is not really an object. It I<is> blessed into the class
C<PMF>, but has no methods except C<call>!
=item *
The syntax is horrible. At least it is not as bad as in C++.
=item *
C<PMF::able> is probably more confusing than useful.
=head1 AUTHOR
Ariel Scolnicov C<E<lt>ariels@compugen.co.ilE<gt>>
=cut
1;