how to pass a function name to a function, and have it call it

N

Nick Wedd

I have a subroutine which draws arcs, I call it like this:
arc( $from, $to, $col, $alist, $trim, $shift, $npoints );
and it draws an arc from $from to $to, with various adornments specified
by the other arguments.

I have a subroutine
sub add {
my ( $p, $q ) = @_;
my ( $x, $y ) = @$p;
my ( $dx, $dy ) = @$q;
return [ $x+$dx, $y+$dy ];
}
which receives a point [$x,$y] and a displacement [$dx,$dy] and returns
the displaced point [$x+$dx,$y+$dy].

I have a subroutine polyarc, which I call like this
my $displist = [ [0,0], [$u,-$u], [-$u,$u] ];
polyarc( $displist, $a, $b, $black, 0, 3 );
It draws a set of arcs, with the specified displacements. Here it is:
sub polyarc {
my ( $displist, $from, $to, @rest ) = @_;
foreach my $d ( @$displist ) {
arc( add($from,$d), add($to,$d), @rest );
}
}

All the above stuff works.

Now I would like to generalise it, to work for subroutines other than
'arc'. I can promise that their first two arguments will be the 'from'
point and the 'to' point, I can't promise anything about the other
arguments. So I want to do something like

sub polyanything {
my ( $displist, $from, $to, $functionname, @rest ) = @_;
foreach my $d ( @$displist ) {
CALL $functionname( add($from,$d), add($to,$d), @rest );
}
}

but, how do I do CALL? I have found googling for "Perl function call"
unhelpful, as you might expect.

Nick
 
P

Peter Makholm

Nick Wedd said:
Now I would like to generalise it, to work for subroutines other than
'arc'. I can promise that their first two arguments will be the 'from'
point and the 'to' point, I can't promise anything about the other
arguments. So I want to do something like

sub polyanything {
my ( $displist, $from, $to, $functionname, @rest ) = @_;
foreach my $d ( @$displist ) {
CALL $functionname( add($from,$d), add($to,$d), @rest );
}
}

but, how do I do CALL? I have found googling for "Perl function call"
unhelpful, as you might expect.

Instead of giving the function name as argument I would prefer to give
a reference to the function as argument. It would look something like
this:

sub polyanything {
my ( $displist, $from, $to, $function, @rest ) = @_;

for my $d (@$displist) {
$function->( add($from, $d), add( $to, $d), @rest );
}
}

And then you would call polyanything like.

polyanything( $displist, $from, $to, \&arc, @rest );

This is documentet in the 'perlref' manual page. Making references
point 1 and using references point 3.

//Makholm
 
D

Dr.Ruud

Sherm said:
Symbolic references (which is what you're asking about here) are evil.
Use a reference to a function instead:

sub somefunc { ... }

sub polyanything {
my ( $displist, $from, $to, $func, @rest ) = @_;
foreach my $d ( @$displist ) {
$func->( add($from, $d), add($to, $d), @rest );
}
}

Then you can call your polyanything with:

polyanything( \@displist, $from, $to, \&somefunc, $foo, $bar, $baz);

Nobody mentioned a dispatch table yet. It is often very handy.
 
J

Jürgen Exner

Nick Wedd said:
Now I would like to generalise it, to work for subroutines other than
'arc'. I can promise that their first two arguments will be the 'from'
point and the 'to' point, I can't promise anything about the other
arguments. So I want to do something like

sub polyanything {
my ( $displist, $from, $to, $functionname, @rest ) = @_;
foreach my $d ( @$displist ) {
CALL $functionname( add($from,$d), add($to,$d), @rest );
}
}

but, how do I do CALL? I have found googling for "Perl function call"
unhelpful, as you might expect.

While from a technical point of view this is possible, in general it is
A Very Bad Idea(TM).
A much, much better approach would be using references, dispatch tables,
and if applicable even closures.

jue
 
N

Nick Wedd

Jürgen Exner said:
While from a technical point of view this is possible, in general it is
A Very Bad Idea(TM).
A much, much better approach would be using references, dispatch tables,
and if applicable even closures.

My thanks to everyone who answered.

Passing a reference to a function with \& , as recommended by Peter
Makholm and Sherm Pendley, is what I was looking for. I have
implemented it and it works.

I had not intended to use symbolic references. They seem to have
something in common with 'eval', so I realise that I would do best to
avoid them.

I have ordered myself a copy of Dominus' book 'Higher-Order Perl'. I
will learn from it what a dispatch table is. Maybe I will even get my
brain round closures at last.

Nick
 
U

Uri Guttman

NW> I had not intended to use symbolic references. They seem to have
NW> something in common with 'eval', so I realise that I would do best to
NW> avoid them.

symrefs aren't directly related to eval but they share the same evil
nature as they can be nasty and dangerous. the rule is use them only
when they are the only or very best solution. they should never be a
first resort if possible (which is what newbies tend to do)

NW> I have ordered myself a copy of Dominus' book 'Higher-Order Perl'.
NW> I will learn from it what a dispatch table is. Maybe I will even
NW> get my brain round closures at last.

dispatch tables have been covered in this newsgroup many many
times. google for that term and you will learn them quickly. they are a
very simple construct - basically a hash with names of ops for keys and
code refs as values. you get the code ref out when you have an op name,
and if it is there, call it. or handle an unknown name with a default
call or error.

uri
 
T

Ted Zlatanov

NW> I have ordered myself a copy of Dominus' book 'Higher-Order Perl'. I
NW> will learn from it what a dispatch table is. Maybe I will even get my
NW> brain round closures at last.

HOP is a complex book by any standard so I wouldn't recommend it to
learn about dispatch tables or closures (both are basic programming
concepts). You'll get lost quickly.

Ted
 

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