Functional Pe(a)rls - the Purely Functional Datastructures edition
-
Upload
osfameron -
Category
Technology
-
view
745 -
download
0
description
Transcript of Functional Pe(a)rls - the Purely Functional Datastructures edition
Functional Pe(a)rls
osfameron @ IPW2011, Turinosfameron @ IPW2011, Turinthe “purely functional data structures” the “purely functional data structures”
editionedition
http://www.fickr.com/photos/jef_saf/3493852795/
previously on Functional Pe(a)rls...
(IPW, LPW, YAPC::EU, nwe.pm)currying
operator references: op(+)Acme::MonadsDevel::Declare
C I A O
C I A O
vs.
0 1 2 3
C I A O
0 1 2 3
0th element
C I A O
0 1 2 3
0th element
M I A OM I A OM I A O
0 1 2 3
0th element
M I A OM I A OM I A O
no kittens were harmed during the making of
this presentation
0 1 2 3
2nd element
M I A O
0 1 2 3
4th element
M I A O
0 1 2 3
max: 3
M I A O
0 1 2 3
max: 3
M I A O
0 1 2 3
max: 4
M I A O W
4th element
4
0 1 2 3
max: 3
M I A O …
100,000
0 1 2 3
max: 3
M I A O
0 1 2 3
max: 4
M I A O W4
0 1 2 3
max: 5
M I A O W !4 5
40 1 2 3
max: 4
M I A O W
0 1 2 3
max: 5
M I A O W !4 5
C I A O
C I A O
vs.
Arrays
C I A O
C I A O
vs.
Perl @arrays“dynamic array”
C I A O
C I A O
C I A O
Head
C I A O
Tail
C I A O
C I A O
I A O
A O
O
C I A O
0th
C A O
nth - 1
I
C A O
nth[2]?
I
nth[1]?
C A OI
nth[0]!nth[2]?
C I A O ?
C I A O ?● tail “ciao” → “iao”
C I A O ?● tail “ciao” → “iao”● tail “iao” → “ao”● tail “ao” → “o”● tail “o” → ?
C I A O ?● tail “ciao” → “iao”● tail “iao” → “ao”● tail “ao” → “o”● tail “o” → “” (the empty string)
C I A O
Head
List =
Tail(another List)
or...
Here comes the science^wPerl!
use MooseX::Declare;
BEGIN { role_type 'List' }
role List { requires 'head'; requires 'tail';}
Moose(X::Declare)
List::Link
class List::Link with List { has head => (
is => 'ro', isa => 'Any'
); has tail => (
is => 'ro', isa => 'List'
), }
List::Link
class List::Link with List { has head => (
is => 'ro', isa => 'Any'
); has tail => (
is => 'ro', isa => 'List'
), }
List::Link
class List::Link with List { has head => (
is => 'ro', isa => 'Any'
); has tail => (
is => 'ro', isa => 'List'
), }
List::Empty
class List::Empty with List { method head {
die "Can't take head of empty list!" } method tail { die "Can't take tail of empty list!" } }
So we can write:
my $list = List::Link->new( head => 'c', tail => List::Link->new( head => 'i', tail => List::Link->new(...
Sugar!
my $list = List->fromArray(qw/ c i a o /);
Multimethods
use MooseX::MultiMethods;
multi method fromArray ($class:) { return List::Empty->new; }
Multimethods
use MooseX::MultiMethods;
multi method fromArray ($class:) { return List::Empty->new; }
Multimethods multi method fromArray ($class: $head, @tail) { return List::Link->new( head => $head, tail => $class->fromArray(@tail), ); }
Eeek! Recursion!
my $list = List::fromArray(1..1000000);
Eeek! Recursion!
my $list = List::fromArray(1..1000000);
Deep recursion on subroutine "List::fromArray" at foo.pl line 20
Eeek! Recursion! multi method fromArray ($class: $head, @tail) { return List::Link->new( head => $head, tail => $class->fromArray(@tail), ); }
Eeek! Recursion!
fromArray
Eeek! Recursion!
fromArray
List::Link->new(..., fromArray)
Eeek! Recursion!
fromArray
List::Link->new(..., fromArray)
List::Link->new(..., fromArray)
Eeek! Recursion!
fromArray
List::Link->new(..., fromArray)
List::Link->new(..., fromArray)
List::Link->new(..., fromArray)
Eeek! Recursion!
fromArray
List::Link->new(..., fromArray)
List::Link->new(..., fromArray)
List::Link->new(..., fromArray)
List::Link->new(..., fromArray)
Eeek! Recursion!
fromArray
List::Link->new(..., fromArray)
List::Link->new(..., fromArray)
List::Link->new(..., fromArray)
List::Link->new(..., fromArray) $list=
Eeek! Recursion!
fromArray
List::Link->new(..., fromArray)
List::Link->new(..., fromArray)
List::Link->new(..., fromArray) $list=
Eeek! Recursion!
fromArray
List::Link->new(..., fromArray)
List::Link->new(..., fromArray) $list=
Eeek! Recursion!
fromArray
List::Link->new(..., fromArray) $list=
Eeek! Recursion!
fromArray $list=
Eeek! Recursion!
no warnings 'recursion';$DB::deep = 100_000_000;
Eeek! Recursion!
no warnings 'recursion';$DB::deep = 100_000_000;
Papering over the cracks
Tail Call Elimination
Sub::Call::TailSub::Call::Recur
by nothingmuch
Tail call elimination
fromArray
Tail call elimination
List::Link->new(..., fromArray)
Tail call elimination
List::Link->new(..., fromArray)
Tail call elimination
List::Link->new(..., fromArray)
Tail call elimination
List::Link->new(..., fromArray)
Tail call elimination
List::Link->new(..., fromArray) $list=
Tail Call Elimination
use Sub::Import 'Sub::Call::Tail' tail => { -as => 'tail_call' };
multi method fromArray ($self: $head, @tail) { tail_call List::Link->new( head => $head, tail => $self->fromArray(@tail), );}
Indexing into List
multi method nth (List::Empty $self: Int $pos)
{ die "Can't index into an Empty list"; }
Indexing into List
multi method nth (Int $pos where { $_ == 0 })
{ return $self->head; }
Indexing into List
multi method nth (Int $pos where { $_ > 0 })
{ tail_call $self->tail->nth( $pos - 1 ); }
C I A O
M
C I A O
M W
C I A O
M WMutation leads to bugs (and misspellings!)
C I A O
M WI A O
C I A O
C I B
C I A O
C I B
Copy everything upstream of a changeDownstream of changes can be shared
C I A O
C I B
Doubly linked lists have no downstream!
O
pure-fp-book
● https://github.com/osfameron/pure-fp-book● Purely Functional Data Structures for the...
● Impure● Perl Programmer● Working Programmer● Mutable, Rank-Scented Many