Upload
osfameron
View
745
Download
0
Embed Size (px)
DESCRIPTION
All new material, this time about one of the fundamental functional datastructures, the Linked List, and the overview of an implementation in Moosey Perl.This covers some of the same material as https://github.com/osfameron/pure-fp-book but perhaps with more explanation (and covering much less material - it was only a 20 minute talk)
Citation preview
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