From: Nick Wedd on
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
--
Nick Wedd nick(a)maproom.co.uk
From: Peter Makholm on
Nick Wedd <nick(a)maproom.co.uk> writes:

> 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
From: Ben Morrow on

Quoth Nick Wedd <nick(a)maproom.co.uk>:
> 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.
<snip>
>
> 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 );
> }
> }

If you're thinking like this, you would probably enjoy Mark-Jason
Dominus' book 'Higher-Order Perl'.

Ben

From: Sherm Pendley on
Nick Wedd <nick(a)maproom.co.uk> writes:

> 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?

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);

sherm--

--
Sherm Pendley <www.shermpendley.com>
<www.camelbones.org>
Cocoa Developer
From: Dr.Ruud on
Sherm Pendley wrote:
> Nick Wedd <nick(a)maproom.co.uk> writes:

>> 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?
>
> 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.

--
Ruud