eklerks has asked for the wisdom of the Perl Monks concerning the following question:

Dear Monks,

I have created an entity, which applies the elements to another entity, but the incantation follows the path of the black arts. I have to call upon another Perl Daemon to grant it life. Please show me my wrongs.

For the less spiritual enlighted:
It is a function, which applies the elements of an array to another function. Like the javascript apply. Here it is:

sub repeat { my $n = shift; my $x = shift; my $array = []; for($i = 0; $i < $n; $i++){ push @{$array}, $x; } return $array; } sub apply { my ($func, $args) = @_; my $size = @{$args}; my $app = repeat($size, '(shift @{$x})'); eval 'sub _apply { my $f = shift; my $x = shift; $f->(' . join +(',', @{$app}) . '); }'; return _apply(\&$func, $args); }

It does its job, but I have understood, that when I call eval another perl interpreter will be started. This is of course not very efficient. Is there a better way to get around this?

I thought about generating a couple of static functions like apply1 apply2 apply3 etc and put it in a package. But I find this offending too.

Example:

sub test { my $x = shift; my $y = shift; my $z = shift; print $x + $y + $z; } # output 6 apply(\&test, [1,2,3]);

Thanks for your help!

Replies are listed 'Best First'.
Re: Applying an array to a function
by BrowserUk (Patriarch) on May 29, 2010 at 23:21 UTC

    This does the same thing?

    #! perl -slw use strict; sub test { my $x = shift; my $y = shift; my $z = shift; print $x + $y + $z; } sub apply2 { my( $code, $argsRef ) = @_; return $code->( @$argsRef ); } apply2( \&test, [1,2,3] );
      Ah yes, I was searching for something like that. I knew I didn't need the eval to achieve my goals. Eval is Evil. Most of the times. If I had took some time, I would have realised, that (pseudocode):
      @t = (1,2,3); test(@t) == test((1,2,3)) == test(1,2,3);
      So the apply function isn't needed either, I can just write (like your example):
      test(@{[1,2,3]});
      Thanks
Re: Applying an array to a function
by choroba (Cardinal) on May 29, 2010 at 23:35 UTC
    What BrowserUk said is what I think as well. You do not need the repeat sub, and if you do for something else, you can shorten it like this:
    sub repeat { my ($n,$x) = @_; my $array = []; @{$array} = ($x) x $n; return $array; }
      Since you were trying to simplify the code, it should be noted that
      my $array = []; @{$array} = ($x) x $n; return $array;
      is a complicated way of writing
      my @array = ($x) x $n; return \@array;
      or
      my $array = [ ($x) x $n ]; return $array;
      or
      return [ ($x) x $n ];
        I use haskell a lot lately and it is nice to see that your last version is very close to how you can implement repeat into haskell:
        repeat a = [a,a..]
        Perl can be a really concise language. It astonish me time after time. I am really looking forward to perl6. (In haskell it is an infinite list, how is this in perl6?)
        I got the answer already. Perl6 is also lazy evaluated, so infinite lists are supported.