Hyper-Multiplying Ethiopians:
Lambdas, Lazyness, & Perl6
Steven Lembark
Workhorse Computing
lembark@wrkhors.com
Hyper-Multiplying Ethiopians:
Lambdas, Lazyness, & Perl6
Welcome to Perl6
Rakudo­Star distro.
Rosetta Code.
Ethiopic Multiplication:
What it is.
More than one way to do it.
Rakudo Star: Perl6 in a tarball
Pretty much what you are used to:
Snag a tarball or pull from GitHub.
perl Configure;
make all test install;
Acquiring Rakudo-Star
Call it “Rakudo” from now on.
http://rakudo.org/
Acquiring Rakudo-Star
Quareterly updates are in ./downloads/star
wget .../rakudo-star-2016.01.tar.gz;
gzip -dc < *.tar.gz | tar xf -;
cd rakudo-star-2016.01;
less README;
Acquiring Rakudo-Star
Quarterly updates are in ./downloads/star
wget .../rakudo-star-2013.10.tar.gz;
gzip -dc < *.tar.gz | tar xf -;
cd rakudo-star-2013.10;
perl Configure.pl –prefix=/opt/perl6 
--backends=moar --gen-nqp --gen-moar &&
make all test install;
Information on Perl6
rakudo.org has links to everything else Perl6­ish.
Rakudo's own doc's page is at:
<http://rakudo.org/documentation>
Also the Perl Maven: Gabor Szabo
<http://perl6maven.com/>
For example:
./parsing-command-line-arguments-perl6
Rosetta Code
Wonderful site, if you care about languages.
Various algorithms, variety of languages. 
Perl6 versions largely coded by Larry Wall.
Ethiopian Multiplication
.../wiki/Ethiopian_Multiplication
Developed in the time of roman numerals:
MCMXIV * XXXIIV = ??
Using integer math:
Halve the first number to 1, double the second. 
Sum doubled numbers for odd halved ones.
Maybe an example will help...
17 x 34 write down two numbers...
Maybe an example will help...
17 x 34
8 halve the first number to 1
4 using integer math...
2
1
Maybe an example will help...
17 x 34
8 68
4 136 double the second number...
2 272
1 544
Maybe an example will help...
17 34
8 68
4 136
2 272
1 544 sum the doubles with odd halves...
Maybe an example will help...
17 34
8 68
4 136
2 272
1 544
578 Viola!, the product
Plan 1: Imperative programming
Loop over the halved value.
Doubling the other.
Summing as you go.
What it looks like in Perl5
sub halve { int((shift) / 2) }
sub double { (shift) * 2 }
sub iseven { ((shift) & 1) == 0 }
sub ethiopicmult
{
my ($plier, $plicand) = @_;
my $r = 0;
while ($plier >= 1)
{
$r += $plicand unless iseven $plier;
$plier = halve $plier;
$plicand = double $plicand;
}
return $r;
}
Perl6
More ways to do it:
Parameter types.
Local functions.
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;
}
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;
}
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;
}
}
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;
}
}
Even more than...
Functional Programming:
Yet Another Way to Avoid Spaghetti Code.
Neither “structured programming” nor “objects”.
Manage state and side effects.
The Evil State
State is hard to maintain.
Coding errors: losing, failed, multiple updates...
Avoiding it reduces errors.
Unintended Consequences
sub loop
{
double $b;
even $a or $r += $b;
halve $a or return $r;
double $b;
}
“Functional” programming
e.g., Haskell, Scheme, Scala, Clojure, Perl6
Declarative: describe the answer not steps.
(e.g., order of execution in Haskell is derived).
Ideal: pure functional code
Fully deterministic function calls.
Avoid state & side­effects.
No surprises.
Easy to test, with full validation.
Catch: it doesn't work
Examples?
time()
random()
readline()
fetchrow_array()
Result: Be realistic.
Looking at it in Perl6
Replace steps with declarations.
Say “how” not “what”.
Declarative definition
sum a list ...
Declarative definition
sum a list ...
selecting the doubled values whose halved 
entry is odd ...
Declarative definition
sum a list ...
selecting the doubled values whose halved 
entry is odd ...
from a list of pairs ...
Declarative definition
sum a list ...
selecting the doubled values whose halved 
entry is odd ...
from a list of pairs ...
halving the first value to one,
doubling the second one each time.
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
);
}
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 ... *
);
}
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 ... *
)
}
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 ... *
)
}
Result
Minimal, declarative syntax.
Avoid order­of­execution errors.
Hopefully more descriptive, easier to maintain.
Result
Minimal, declarative syntax.
Avoid order­of­execution errors.
Hopefully more descriptive, easier to maintain.
But wait!
There's More!
What you are used to
Processing a list with map:
@result = map { $_->$method( @argz ) } @inputs;
Single­threaded.
Fixed order of input.
Fixed order of processing.
Perl6 adds “hyperoperators”
The “»” or “>>” parallel execution:
@result = @objects».&function( @args );
@objects  blessed or class, literal or variable.
@result   in the same order as @objects.
Order of execution is indeterminate.
Zipping pairs, not flat lists.
“zip” generates a flat list.
“Z=>” normally used for hashes:
my %hash =
( ( $a, * div 2 … 1 ) Z=> ( $b, * * 2 … * ) );
List of key:value pairs:
( ( 17, 34 ) ; ( ( 8, 68 ) ; … )
Processing pairs
Pair object has “key” and “value”:
sub odd_values( $pair )
{
$pair.key % 2 ?? $pair.value !! ()
}
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 single­threaded.
Hyper-whybotherators?
“$a % 2” ??
Comparing DNA or proteins...
… complex financial simulation...
… playing conway's game of life?
without loops, forks, breaks, joins, 
co routines, or queues?‑
What's this got to do with FP?
Hyperoperators lack repeatable sequence.
Side effects, state?
Fix: FP [­ish] functions for hyperoperators.
Reading on the ceiling
Catch: map­ish code reads “upside down”.
Wish you could read it going down the page?
Feeding on the floor
Feed operator:
( ( $a, * div 2 … 1 ) Z=> ( $b, * * 2 … * ) ) 
».odd_values ==> [+]
odd_values into [+] block­iterator.
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 ==> [+]
}
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.
Shameless Plug
Glacier Hashes are nice for FP.
Perl5 is nice for Glacier Hashes.
YAPC::NA 2016: FP code & benchmarks.
With tail recursion.
In Perl5. 
References
Monads in Perl5:
http://web.archive.org/web/20080515195640/http://sle
epingsquirrel.org/monads/monads.html
Introduces the basic ideas of functional 
programming with monads using Perl5 examples.
References
Readable descriptions of “Monad”:
https://stackoverflow.com/questions/44965/what-is-a-
monad
https://stackoverflow.com/questions/2704652/monad-
in-plain-english-for-the-oop-programmer-with-no-fp-
background
References
What databases mean to Functional Programming:
<https://stackoverflow.com/questions/8406261/most
­common­pattern­for­using­a­database­in­a­
functional­language­given­desire>
The most common pattern for dealing with side­
effects and impurity in functional languages is:
    ­ be pragmatic, not a purist ...
References
Realistic view of FP:
https://stackoverflow.com/questions/330371/are-
databases-and-functional-programming-at-odds
Functional languages do not have the goal to 
remain stateless, they have the goal to make 
management of state explicit.
References
Good overview of the vocabulary:
http://en.wikipedia.org/wiki/Functional_Programming
References
Academic description of Monads:
http://web.archive.org/web/20071128090030/http://hom
epages.inf.ed.ac.uk/wadler/papers/marktoberdorf/baas
tad.pdf

Ethiopian multiplication in Perl6