Prev: FAQ 7.21 How do I redefine a builtin function, operator, or method?
Next: FAQ 8.14 How do I modify the shadow password file on a Unix system?
From: Nick Wedd on 6 Jul 2010 08:50 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 6 Jul 2010 09:05 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 6 Jul 2010 09:34 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 6 Jul 2010 10:38 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 6 Jul 2010 11:36
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 |