Perl6 introduces a variety of tools for functional programming and writing readable code. Among them parameter declarations and lazy lists. This talk looks at how to get Perl6, where to find examples on RakudoCode, and how to use Perl6 functional tools for converting an algorithm from imperative to functional code, including parallel dispatch with the ">>" operator.
18. Stand-alone subs
sub halve (Int $n is rw) { $n div= 2 } # integer divide
sub double (Int $n is rw) { $n *= 2 }
sub even (Int $n --> Bool) { $n %% 2 } # return, is-divisible
sub ethiopicmult
(
Int $a is copy, Int $b is copy --> Int
)
{
my $r = 0;
while $a
{
even $a or $r += $b;
halve $a;
double $b;
}
return $r;
}
19. Embedded subs
sub ethiopicmult
(
Int $a is copy, Int $b is copy --> Int
)
{
sub halve (Int $n is rw) { $n div= 2 }; # subs are
sub double (Int $n is rw) { $n *= 2 }; # lexically
sub even (Int $n --> Bool) { $n %% 2 }; # scoped
my $r = 0;
while $a
{
even $a or $r += $b;
halve $a;
double $b;
}
return $r;
}
20. Self-contained with lexical subs
sub ethiopicmult
(
Int $a is copy, Int $b is copy --> Int
)
{
my &halve = * div= 2; # placeholders save
my &double = * *= 2; # syntax.
my &even = * %% 2;
my $r = 0;
loop # a.k.a. for(;;)
{
even $a or $r += $b;
halve $a or return $r;
double $b;
}
}
21. Self-contained with lexical subs
sub ethiopicmult
(
Int $a is copy, Int $b is copy --> Int
)
{
state &halve = * div= 2; # “state” avoids
state &double = * *= 2; # re-compiling.
state &even = * %% 2;
my $r = 0;
loop
{
even $a or $r += $b;
halve $a or return $r;
double $b;
}
}
33. Iterators & maps & zips, oh my!
sub ethiopicmult
( Int $a is copy, Int $b is copy --> Int )
{
state &halve = * div= 2;
state &double = * *= 2;
state &odd = * % 2;
[+] # list operator [] iterates '+'.
map # map pulls two values each time.
{
$^col_2 if odd $^col_1 # parameters extract in lexical order.
},
zip # new list from the list arguments
(
$a, &halve ... 1 ; # semi-colon separates lists
$b, &double ... * # indefinite lazy list
);
}
34. Iterators & maps & zips, oh my!
sub ethiopicmult
( Int $a is copy, Int $b is copy --> Int )
{
state &halve = * div= 2;
state &double = * *= 2;
[+]
map -> $half, $dbl # named parameters
{
$dbl if $half % 2
},
zip
(
$a, &halve ... 1 ;
$b, &double ... *
);
}
35. Inline list generators replace subs
sub ethiopicmult
( Int $a is copy, Int $b is copy --> Int )
{
# what you see is all you get
[+]
map -> $half, $dbl
{
$dbl if $half % 2
},
zip
(
$a, * div 2 ... 1 ; # implicit subs
$b, * * 2 ... *
)
}
36. Ternary Operator Makes 0 Explicit
sub ethiopicmult
{
my ($a,$b) = @_; # still works
[+]
map -> $half, $dbl
{
$half % 2
?? $dbl # wider ?? !! easier to see
!! 0 # or ()
},
zip
(
$a, &halve ... 1;
$b, &double ... *
)
}
39. What you are used to
Processing a list with map:
@result = map { $_->$method( @argz ) } @inputs;
Singlethreaded.
Fixed order of input.
Fixed order of processing.
43. Generating the list of odd values
[+]
( ( $a, * div 2 … 1 ) Z=> ( $b, * * 2 … * ) )
».odd_values
Selection of odd values is parallel.
Generation and sum are singlethreaded.
45. What's this got to do with FP?
Hyperoperators lack repeatable sequence.
Side effects, state?
Fix: FP [ish] functions for hyperoperators.
46. Reading on the ceiling
Catch: mapish code reads “upside down”.
Wish you could read it going down the page?
47. Feeding on the floor
Feed operator:
( ( $a, * div 2 … 1 ) Z=> ( $b, * * 2 … * ) )
».odd_values ==> [+]
odd_values into [+] blockiterator.
48. The result
sub ethiopic_hyper_mult( $a, $b )
{
sub odd_values( $pair )
{ $pair.key % 2 ?? $pair.value !! () }
(( $a, * div 2 … 1 ) Z=> ( $b, * * 2 … * ) ))
>>.&odd_values ==> [+]
}
49. New things in Perl6
%% is “Divisible By" & "div" integer division.
my &subname = ... for lexically defined subs.
* for parameters.
$^foo for block parameters.
Parameterized lists with $start, OP, $end.
List operators with [ OP ].
Hyperopertors & friends.