functional pe(a)rls: huey's zipper
DESCRIPTION
2014 edition of the Functional Pe(a)rls series, this time on purely functional Zippers with Moo, and self-balancing AA trees.TRANSCRIPT
FUNCTIONAL PE(A)RLSYAPC::EU::2014 София
@osfameron
Huey’s Zipper
http://marinaneira.deviantart.com/art/Huey-Duck-317018337
FUNCTIONAL PE(A)RLS WORLD TOUR
IPW 2008, Pisa map/grep, lazy iterators, currying, Devel::Declar for pretty syntax, Concurrency (Acme::Fork::Lazy)
LPW 2008, London much of above, Monad tutorial, Devel::Declare, Imperative programming in Pure Perl!
NWE.pm May 2009, Manchester as above, possibly also pattern matching?
YAPC::EU 2009, Lisbon functions, operators, Devel::Declare, sections, partial application, Sub::Curried, composition
IPW 2011, Turin purely functional data structures, linked lists,
http://www.slideshare.net/osfameron/
https://www.flickr.com/photos/qiaomeng/5540694558/
https://www.flickr.com/photos/hoyvinmayvin/4686704193/
IN THE BLUE CORNER…
Mutable
my $x = 10;
…
$x = 20;
Immutable
my $x = 10;
…
my $x2 = 20;
AND IN THE RED CORNER…
Mutable
sub c2f {my $temp=shift;$temp *= 9;$temp /= 5;$temp += 32;return $temp;
}
Immutable
sub c2f {my $c=shift;my $t1 = $c * 9;my $t2 = $t1 / 5;my $f = $t2 + 32;return $f;
}
AND IN THE RED CORNER… (redux)
Mutable
sub c2f {my $temp=shift;$temp *= 9/5;$temp += 32;return $temp;
}
Immutable
sub c2f {my $c = shift;return (
($c * 9/5)+ 32
)}
https://www.flickr.com/photos/redvers/532076662/
MUTABLE… CONSTANTS?
1 = 2;
say 1 + 1; # 4
ACTION AT A DISTANCE
my $one = 1;
…
sub bad_mutation {$one++;
}
sub naïve_expectations {say $one + $one; # 2? Or 4, 6, 10, etc.?
}
CONSTANTS
use constant ONE => 1;
…
sub on_the_defensive {say ONE + ONE; # 2
}
https://www.flickr.com/photos/jans_world/8985026701/
IMMUTABLE DATA STRUCTURES…
my $users = { … };
my $users_with_addresses = frobnicate($users);
send_emails($users_with_addresses);
sub send_emails {my $in = shift;my $intermediate = doozle($in);…return $out
}
IMMUTABLE DATA STRUCTURES…
my $users = { … };
my $users_with_addresses = frobnicate($users);
send_emails($users_with_addresses);
sub send_emails {my $in = shift;my $intermediate = doozle($in);…return $out
}
IMMUTABLE DATA STRUCTURES…
my $users = { … };
my $users_with_addresses = frobnicate($users);
send_emails($users_with_addresses);
sub send_emails {my $in = shift;my $intermediate = doozle($in);…return $out
}
https://www.flickr.com/photos/light_seeker/7571188852/
READONLY VARIABLES
use Const::Fast;
sub wibble {const my $in => shift;const my $out => $in * 2;return $out;
}
READONLY VARIABLES
const my %hash => (foo => {
bar => 1}
);
$hash{foo}{bar} = 2; # tee hee hee
READONLY VARIABLES
const my %hash => (foo => {
bar => 1}
);
$hash{foo}{bar} = 2;
# Modification of a read-only value attempted
COPIES OF VARIABLES?
Mutable
sub c2f {my $temp=shift;$temp *= 9;$temp /= 5;$temp += 32;return $temp;
}
Immutable
sub c2f {my $c=shift;my $t1 = $c * 9;my $t2 = $t1 / 5;my $f = $t2 + 32;return $f;
}
https://www.flickr.com/photos/historiska/13619294395
CREATURE COMFORTS
package Creature;
use Moo;
use Types::Standard ‘:all’;
has name => ( is => ‘ro’, isa => Str );
has type => ( is => ‘ro’, isa => Str );
has height => ( is => ‘ro’, isa => Num );
IF IT QUACKS LIKE A DUCK
use Creature;
my $donald = Creature->new(name => ‘Donald’,type => ‘duck’,height => 50, # cm
);
RESEARCH
http://wiki.answers.com/Q/How_tall_is_Donald_duck
RESEARCH
https://www.google.co.uk/search?q=2+feet+in+cm
LET’S JUST CHANGE THAT THEN, OH…
$donald->height( 60.96 );
CREATURE COMFORTS
package Creature;
use Moo;
use Types::Standard ‘:all’;
has name => ( is => ‘ro’, isa => Str );
has type => ( is => ‘ro’, isa => Str );
has height => ( is => ‘ro’, isa => Num );
CHAINED COPY…
# using MooseX::Attribute::ChainedClone
my $donald2 = $donald->height( 60.96 );
https://www.flickr.com/photos/dps/7161557/
CHAINED COPY…
# using MooseX::Attribute::ChainedClone
my $donald2 = $donald->height( 60.96 );
MooX::But
package MooX::But;
use Moo::Role;
sub but {
my $self = shift;
return $self->new(%$self, @_);
}
# see https://github.com/haarg/MooX-CloneWith
CHAINED COPY…
my $donald2 = $donald->but( height => 60.96 );
https://www.flickr.com/photos/randar/10337132166/
I’LL BE A MONKEY’S UNCLE
package Creature;
use Moo;
use Types::Standard ‘:all’;
has name => ( is => ‘ro’, isa => Str );
has type => ( is => ‘ro’, isa => Str );
has height => ( is => ‘ro’, isa => Num );
has uncle => ( is => ‘ro’,isa => InstanceOf[‘Creature’] );
COMPLEX CHAINED COPIES…
Mutable
$donald->uncle->height(52);
Immutable
$donald->uncle->but(height => 52
);
COMPLEX CHAINED COPIES…
Mutable
$donald->uncle->height(52);
Immutable
my … = $donald->uncle->but(height => 52
);
COMPLEX CHAINED COPIES…
my $donald2 = $donald->but(uncle => $donald->uncle->but(
height => 52)
);
https://www.flickr.com/photos/81583603@N00/4099146279/
EVEN MOAR COMPLEX CHAINED COPIES…
my $huey = $huey->but(uncle => $huey->uncle->but(
uncle => $huey->uncle->uncle->but(height => 52,
))
);
https://en.wikipedia.org/wiki/Clan_McDuck#Family_tree
http://pixdaus.com/super-squirrel-squirrel/items/view/97702/
THE ZIPPER
my $zipper = $huey->zip;
THE ZIPPER
my $zipper = $huey->zip->go(‘uncle’);
THE ZIPPER
my $zipper = $huey->zip->go(‘uncle’)->go(‘uncle’);
https://www.flickr.com/photos/nics_events/2349632625/
MODIFYING “IN-PLACE”
my $zipper = $huey->zip->go(‘uncle’)->go(‘uncle’)->set( height => 51 );
BACK UP THE ZIPPER
my $zipper = $huey->zip->go(‘uncle’)->go(‘uncle’)->set( height => 51 )->up;
BACK UP THE ZIPPER
my $zipper = $huey->zip->go(‘uncle’)->go(‘uncle’)->set( height => 51 )->up->up;
https://www.flickr.com/photos/123755251@N04/13969035991
UNZIPPING
my $huey2 = $huey->zip->go(‘uncle’)->go(‘uncle’)->set( height => 51 )->up->up->unzip;
UNZIPPING
my $huey2 = $huey->zip->go(‘uncle’)->go(‘uncle’)->set( height => 51 )->up->up->unzip;
UNZIPPING
my $huey2 = $huey->zip->dive(‘uncle’, ‘uncle’)->set( height => 51 )->unzip;
UNZIPPING
my $huey2 = $huey->doZipper( sub { $_->dive(‘uncle’, ‘uncle’)->set( height => 51 ) } );
REMATCH
Mutable
$huey->uncle->uncle->height(51);
Immutable
my $huey2 = $huey->doZipper(sub {
$_->uncle->uncle->set(height=>51)
});
REMATCH
Mutable
$huey->uncle->uncle->height(51);
Immutable
my $huey2 = $huey->doZipper(sub {
$_->uncle->uncle->set(height=>51)
});
https://www.flickr.com/photos/phunk/1460508385/
https://www.flickr.com/photos/mukumbura/3845329580/
https://www.flickr.com/photos/93081182@N02/12853918764/
https://www.flickr.com/photos/intherough/3470183543/
https://www.flickr.com/photos/ruthanddave/1760267748/
RED BLACK TREES
https://en.wikipedia.org/wiki/Red%E2%80%93black_tree
https://www.flickr.com/photos/bunnyrel/3970251151/
TYPICAL RED-BLACK TREE CASES
https://en.wikipedia.org/wiki/AA_tree
http://www.quickmeme.com/Engineering-Professor/page/43/
AA TREE CASES
https://en.wikipedia.org/wiki/AA_tree
https://www.flickr.com/photos/wwarby/7127632463/
BALANCING ROTATIONS
Skew Split
ZIPPER WITHIN AA-TREE CODE
# split
return $R->but(
left => $self->but(
right => $R->left,
),
level => $R->level + 1,
);
ZIPPER WITHIN AA-TREE CODE
# split
return $R->but(
left => $self->but(
right => $R->left,
),
level => $R->level + 1,
);
ZIPPER WITHIN AA-TREE CODE
# split
return $R->zip
->set( level => $R->level + 1)
->left->set( right => $R->left )
->unzip;
ZIPPER WITHIN AA-TREE CODE
# split
return $R->zip
->inc(‘level’)
->left->set( right => $R->left )
->unzip;
https://www.flickr.com/photos/jimmiehomeschoolmom/5066802611
ZIPPER WITHIN AA-TREE CODE
# in delete
$tree = $tree->zip
->set( level => $min_level )
->right->set( level => $min_level2 )
->top->skew->right->skew->right->skew
->top->split->right->split
->unzip;
ZIPPER WITHIN AA-TREE CODE
# in delete
$tree = $tree->zip
->set( level => $min_level )
->right->set( level => $min_level2 )
->top->skew->right->skew->right->skew
->top->split->right->split
->unzip;
ZIPPER WITHIN AA-TREE CODE
# in delete
$tree = $tree->zip
->set( level => $min_level )
->go(‘right’)->set( level => $min_level2 )
->top->skew->go(‘right’)->skew->go (‘right’)->skew
->top->split->go(‘right’)->split
->unzip;
ZIPPER WITHIN AA-TREE CODE
# in delete
$tree = $tree->zip
->set( level => $min_level )
->right->set( level => $min_level2 )
->top->skew->right->skew->right->skew
->top->split->right->split
->unzip;
LendingMemo.com - https://www.flickr.com/photos/lendingmemo/11702093735/
https://www.flickr.com/photos/wwworks/4759535950/