6

Say I want to apply an array of functions to an array of objects. Something like this:

my $a = sub ($) { $_ * 2 };
my $b = sub ($) { $_ / 2 };

my @funcs = ($a, $b);

my @ops = @funcs.roll(4);

I could do

say  ^10 ».&» @ops; 

but .& is a postfix operator; same thing for >>., which could be used for a single function, however. Using

say  ^10 Z. @ops; 

with . actually being the infix operator for calling a method, yields an error about mistaking it for the concatenation operator. I don't think I have any other option left. Any idea?

jjmerelo
  • 22,578
  • 8
  • 40
  • 86

3 Answers3

6

You could use the &infix:« o » / &infix:« ∘ » operator, combined with a lambda/closure factory.

sub lambda-factory ( +in ) {
  in.map: -> \_ { ->{_} }
}

my @funcs = (
  * * 2,
  * / 2
);

(@funcs X∘ lambda-factory ^10)».()
# (0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5)

(@funcs «∘» lambda-factory ^10)».()
# [0, 0.5, 4, 1.5, 8, 2.5, 12, 3.5, 16, 4.5]

( (|@funcs xx *) Z∘ lambda-factory ^10 )».()
# (0, 0.5, 4, 1.5, 8, 2.5, 12, 3.5, 16, 4.5)
Brad Gilbert
  • 33,846
  • 11
  • 78
  • 129
  • 1
    No easier way to do that? If I got that correctly, you are building a pointy block out of the arguments to be able to apply the function to them, right? OK; I see, you are creating a new function out of the arguments and applying them... right. – jjmerelo Apr 02 '18 at 16:36
4

If you have defined values, you can use the infix operator andthen.

    say (^10 »andthen» (* * 2, * / 2).roll(4))
wamba
  • 3,883
  • 15
  • 21
1

If you roll your own infix equivalent of .& the construct you are trying to create seems to work fine.

$ perl6 -e 'my sub infix:<foo> ($a, $b) { $b($a) }; say ^10 Z[foo] (-> $_ { $_*2 }, -> $_ { $_/2 }).roll(4);'
(0 0.5 1 6)
Brian Julin
  • 71
  • 1
  • 3