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

Hi,
(Update it is not an problem with operators in rakudo)
(Update perl5 code fails because $f and $g aren't local in my original code, as almut points out)

I was trying to create a composition operator in perl. I know it is too simple, it only accepts functions, which have 1 argument, but that isn't the problem:

sub infix:<!*> (&f, &g) { return sub ($x) { return f(g($x)); }; }

It works when I make a composition of 2 functions:

sub test ($x) { return $x ~ " test"; } # outputs (&test !* &test) test test say (&test !* &test)('&test !* &test');

When I try to composite 3 functions, it gets a bit wacky:

# Fails with too much recursion say (&test !* (&test !* &test))('&test !* &test !* &test');

When I try to first assign the working case to a variable and then composite it with another function, I get an even stranger result:

my $p = &test !* &test; my $q = $p !* &test; # outputs $p = &test !* &test test say $p('$p = &test !* &test'); #should be $p !* test test test (?), but says $p !* test test say $q('$p !* &test');

I wrote it in a comparable way for javascript to see and perl5, if it was working there. <s>In perl5 it didn't work either</s> and in javascript it did:

(Runned with rhino)
function comp(f, g){ return function(x){ return f(g(x)); } } function test(x){ return x + " test"; } print (comp(test,comp(test,test))("test "));

Failing perl5 code

sub comp { $f = shift; $g = shift; return sub { $x = shift; return $f->($g->($x)); }; } sub test { return (shift) . " test"; } print comp(\&test, comp(\&test,\&test))->("test ");

Correct perl5 code

sub comp { my ($f, $g) = @_; return sub { my $x = shift; return $f->($g->($x)); }; } sub test { return (shift) . " test"; } print comp(\&test, comp(\&test,\&test))->("test ");

The code on rosettacode.org has the same problem. (perl6)

Is this a bug, or is this something I clearly don't understand?

Replies are listed 'Best First'.
Re: Rakudo function composition problem
by almut (Canon) on Jun 03, 2010 at 13:52 UTC

    (OP updated node after my reply)

    As for the Perl 5 version, try lexical variables (i.e. my) for $f, $g and $x.  (outputs "test  test test test" for me)

      Thanks! I realised the error, (but you were faster ;)) I wrote it a bit fast and sloppy. I updated the node.