Hi, Todd & Jeff, :) From: "Jeff 'japhy' Pinyan" <[EMAIL PROTECTED]> > On Nov 13, todd shifflett said:
>> the above works. Now I would like to be able to pass in a >> subroutine from a declared object. > You mean a "method" (that is, a function that is "bound" to an object). >> my $fft = new Math::FFT(\@nums); >> print foo(\&{'fft->stdev'},\@nums); > You want to use the UNIVERSAL::can method: > my $fft = Math::FFT->new(\@nums); > print foo($fft->can('stdev'), \@nums); > perldoc UNIVERSAL _The Perl Cookbook_, in the recipe from which I quoted earlier (11.8), specifically considers this solution and has this to say: "The 'can' method from the UNIVERSAL base class, while appealing, is also unlikely to produce what you want. $cref = $obj->can( "meth" ); This produces a code ref to the appropriate method (should one be found), one that carries *no* *object* *information*. Think of it as a raw function pointer. The information about the object is lost. That's why you need a closure to capture both the object state as well as the method call." (Emphasis is mine.) I rewrote Todd's test FFT script to be: #!/usr/bin/perl use strict; use warnings; use Math::FFT; my @nums = qw(3 4 5 7 10 8 7 9); my $fft = new Math::FFT( \@nums ); # my $stdev = sub { $fft->stdev( @_ ) }; # print foo( $stdev, \@nums ); my $cref = $fft->can( "stdev" ); print foo( $cref, \@nums ); sub foo { my($f, @args) = @_; return $f->( @args ); } When I ran this, it failed. Here is the result of my running it under Cygwin Perl: $ ./ref.pl Can't coerce array into hash at /usr/lib/perl5/site_perl/5.6.1/cygwin-multi/Math/FFT.pm line 500. I don't entirely understand what this error means. Here is the source of the Math::FFT->stdev() method: sub stdev { my $self = shift; my ($n, $data, $mean); if ($data = shift) { die 'Must call with an array reference' unless ref($data) eq 'ARRAY'; $n = @$data; $mean = $self->mean($data); } else { -> $data = $self->{data}; $n = $self->{n}; $mean = $self->{mean} || $self->mean; } die 'Cannot find the standard deviation with n = 1' if $n == 1; my $sum = 0; $sum += ($_ - $mean)*($_ - $mean) for @$data; return sqrt($sum / ($n-1)); } In my version of the module (0.25), line 500 is the first line in the 'else' block (pointed to by the arrow). What appears to be happening is this: Since the function pointer returned by '->can()' does not relate to a specific object, the implicit '$self' parameter is not pushed on to the head of the argument list. This means that the only argument to 'stdev()' is actually the array reference '\@nums'. The first line of the method thus sets '$self' to the array reference. Since there aren't any more args, the routine drops into the 'else' block. The first line fails because it's trying to use the array reference ('\@nums') stored in '$self' as a hash reference. OK, now I *really* believe that TPC recipe. ;> Todd: I hope that this isn't completely opaque and actually has some meaning. I believe that you really do need to use the closure strategy (commented in my little example above) if you want to capture the object's state as well as the method pointer. Good luck! ---Jason Sonos Handbell Ensemble http://www.sonos.org/ P.S. - I get the impression that the '->can()' strategy would work if you were trying to call a "static" method; i.e. one that didn't depend on operating on a specific object instance and thus getting the implicit '$self' first argument. -- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]