Functional Pe(a)rls version 2
Upcoming SlideShare
Loading in...5
×
 

Like this? Share it with your network

Share

Functional Pe(a)rls version 2

on

  • 3,550 views

Some techniques from the heady world of Functional Programming implemented in idiomatic Perl using various techniques: closures, iterators, Devel::Declare, and some distilled evil. New version now ...

Some techniques from the heady world of Functional Programming implemented in idiomatic Perl using various techniques: closures, iterators, Devel::Declare, and some distilled evil. New version now with monads! (As presented at http://conferences.yapceurope.org/lpw2008/ )

Statistics

Views

Total Views
3,550
Views on SlideShare
3,547
Embed Views
3

Actions

Likes
2
Downloads
39
Comments
0

1 Embed 3

http://www.slideshare.net 3

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Functional Pe(a)rls version 2 Presentation Transcript

  • 1. Functional pe(a)rls
      • London Perl Workshop
      • 29/11/2008
      • version 2
      • osfameron
  • 2. A sequence
    • Debolaz, on #moose
    • a list of numbers like
      • 10, 25, 50,
      • 100, 250, 500,
      • 1000, etc
    • without tracking any other state than the number itself
  • 3. A sequence
    • 1. (power of 10) * 2.5
    • 2. * 2
    • 3. * 2
  • 4. A sequence
      • without tracking any other state than the number itself
  • 5. A sequence
      • /^1/
  • 6. A sequence
      • /^1/ # power of 10
  • 7. A sequence
    • cycle [2.5, 2, 2]
  • 8. A sequence
    • cycle [2.5, 2, 2]
      • 2.5
      • 2
      • 2
      • 2.5
      • ...
  • 9. A sequence
    • Oops!
    • Perl doesn't have infinite sequences
  • 10. A sequence
      • Iterators
  • 11. A sequence
      • curry cycle (@list) {
      • my @curr = @list;
      • return sub {
      • @curr = @list
      • unless @curr;
      • return shift @curr;
      • };
      • }
  • 12. A sequence
    • my $c = cycle [2.5, 2, 2];
  • 13. A sequence
    • my $c = cycle [2.5, 2, 2];
      • say $c->(); # 2.5
      • say $c->(); # 2
      • say $c->(); # 2
      • say $c->(); # 2.5
      • ...
  • 14. A sequence cycle [2.5, 2, 2];
  • 15. A sequence 10, cycle [2.5, 2, 2];
  • 16. A sequence mult, 10, cycle [2.5, 2, 2];
  • 17. (curry)‏
      • curry mult ($x,$y) {
      • $x * $y
      • }
  • 18. (curry)‏
      • say mult( 3, 4 );
      • # 12
  • 19. (curry)‏
      • my $triple = mult(3);
      • say $triple->(10);
      • # 30
  • 20. (curry)‏
      • my $multiply = mult;
      • say $multiply->(6, 8);
  • 21. (curry)‏
      • my $multiply = &mult;
      • my $multiply = mult;
  • 22. A sequence mult , 10, cycle [2.5, 2, 2];
  • 23. A sequence scan mult, 10, cycle [2.5, 2, 2];
  • 24. (Scanning)‏ scan add, 1, [2, 3, 4]; # [1, 3, 6, 10]
  • 25. A sequence scan mult, 10, cycle [2.5, 2, 2];
  • 26. A sequence take 12 => scan mult, 10, cycle [2.5, 2, 2];
  • 27. A sequence say for take 12 => scan mult, 10, cycle [2.5, 2, 2];
  • 28. A sequence
    • 10
    • 25
    • 50
    • 100
    • 250
    • 500
    • ...
  • 29. How?
    • Iterators (HOP)‏
      • HOP::Stream
      • Lazy variables
  • 30. How?
    • Iterators (HOP)‏
    • FP (scan, take)‏
  • 31. How?
    • Iterators (HOP)‏
    • FP (scan, take)‏
    • Sub::Curried
  • 32. How?
    • Iterators (HOP)‏
    • FP (scan, take)‏
    • Sub::Curried
    • Devel::Declare
  • 33. Devel::Declare
      • curry mult ($x,$y) {
      • $x * $y
      • }
  • 34. Devel::Declare
    • New syntax!
    • (But better than source filters)‏
  • 35. Devel::Declare
    • New syntax!
    • (But better than source filters)‏
      • Method declaration
      • MooseX::Declare
      • Sub::Auto
  • 36. Devel::Declare
    • New syntax!
    • (But better than source filters)‏
      • Currying
      • Monads
      • Pattern Matching
      • List comprehensions
      • Functions that work on @arrays and lists
  • 37. Devel::Declare
    • In Perl!
    • (With a bit of scary XS magic)‏
      • hooks into the compiler
      • changing the source as you compile
      • horrible perl tricks to get methods installed, and braces closed
      • mst++, rafl++
  • 38. Some light relief
  • 39. Some light relief Monads
  • 40. Monads
    • Come from maths
    • “ Category theory”
  • 41. Monads
    • Come from maths
    • “ Category theory”
    • Very clever people rave about them being useful
  • 42. Monads
    • Come from maths
    • “ Category theory”
    • Very clever people rave about them being useful
    • Have a reputation for being hard to understand
  • 43. Monad tutorials
  • 44. Monad tutorials
  • 45. Monad tutorials
  • 46. Monad tutorials
  • 47. Monad tutorials Step 1: Write Monad Tutorial
  • 48. Monad tutorials Step 2: ???
  • 49. Monad tutorials Step 3: Profit!
  • 50. Monads
    • You already use monads
  • 51. Monads
    • You already use monads
    • YAY!
  • 52. Monads
    • You already use monads
    • Sequences of commands?
  • 53. Sequencing my $x = 1; my $y = 2; my $z = $x * $y; say “$x * $y = $z”;
  • 54. Sequencing my $x = 1; my $y = 2; my $z = $x * $y; say “$x * $y = $z”;
  • 55. Sequencing my $x = 1; my $y = 2; my $z = $x * $y; say “$x * $y = $z”;
  • 56. Sequencing my @seq = sub { my $x = 1 }, sub { my $y = 2 }, sub { my $z = $x * $y }, sub { say "$x * $y = $z" };
  • 57. Sequencing my @seq = sub { my $x = 1 }, sub { my $y = 2 }, sub { my $z = $x * $y }, sub { say "$x * $y = $z" }; # Global symbol "$x" requires explicit package name at ...
  • 58. Nesting my $x = 1; my $y = 2; my $z = $x * $y; say “$x * $y = $z”;
  • 59. Nesting sub { my $x = 1; sub { my $y = 2; sub { my $z = $x * $y; sub { say "$x * $y = $z"; }->() }->() }->() }->();
  • 60. Monads made pretty
    • Source filters!
      • http://sleepingsquirrel.org/monads/monads.html
  • 61. Monads made pretty
    • Source filters!
      • http://sleepingsquirrel.org/monads/monads.html
    • Source tree manipulation (B::OP magic)‏
    • Deparse and source text munging
  • 62. Monads made pretty
    • We want a syntax like
    • mdo { my $x = mbind(1); my $y = mbind(2); my $z = mbind($x + $y); say “$x * $y = $z”; }
  • 63. Monads made pretty
    • We want a syntax like
    • mdo { my $x = mbind(1); my $y = mbind(2); my $z = mbind($x + $y); say “$x * $y = $z”; }
    • mdo introduces the block
    • mbind gives us a hook to rotate around
  • 64. Optree munging
    • 19: my $x << Just 2; ... n <;> nextstate(main 2078 b.pl:19) v:*,&,$ ->o t <2> left_shift[t3] vK ->u o <0> padsv[$x:2078,2080] sM/LVINTRO ->p s <1> entersub[t2] sKS/TARG,3 ->t - <1> ex-list sK ->s p <0> pushmark s ->q q <$> const(IV 2) sM ->r - <1> ex-rv2cv sK/130 ->- r <$> gv(*Just) s ->s u <;> nextstate(main 2079 b.pl:20) v:*,&,$ ->v
    • # : mbind (Just 2), sub { my $x = shift; ... }; <;> nextstate(main b.pl:) v:*,&,{,$ -> <@> list K -> <0> pushmark s -> <1> entersub[t2] KS/TARG,3 -> - <1> ex-list K -> <0> pushmark s -> <1> entersub[t1] lKMS/NO(),TARG,INARGS,3 -> - <1> ex-list lK -> <0> pushmark s -> <$> const(IV 2) sM -> - <1> ex-rv2cv sK/130 ->- <$> gv(*Just) s -> - <1> ex-rv2cv sK/2 ->- # mbind instead of >> <$> gv(*mbind) s -> <1> refgen K/1 -> - <1> ex-list lKRM -> <0> pushmark sRM -> <$> anoncode[CV ] lRM -> # ??? set up anon sub # my $x = shift <0> padsv[$x:2078,2080] sM/LVINTRO ->p # the next ; is moved into this new lambda! <;> nextstate(main 2079 b.pl:20) v:*,&,$ ->v
  • 65. Optree munging
    • 19: my $x << Just 2; ... n <;> nextstate(main 2078 b.pl:19) v:*,&,$ ->o t <2> left_shift[t3] vK ->u o <0> padsv[$x:2078,2080] sM/LVINTRO ->p s <1> entersub[t2] sKS/TARG,3 ->t - <1> ex-list sK ->s p <0> pushmark s ->q q <$> const(IV 2) sM ->r - <1> ex-rv2cv sK/130 ->- r <$> gv(*Just) s ->s u <;> nextstate(main 2079 b.pl:20) v:*,&,$ ->v
    • # : mbind (Just 2), sub { my $x = shift; ... }; <;> nextstate(main b.pl:) v:*,&,{,$ -> <@> list K -> <0> pushmark s -> <1> entersub[t2] KS/TARG,3 -> - <1> ex-list K -> <0> pushmark s -> <1> entersub[t1] lKMS/NO(),TARG,INARGS,3 -> - <1> ex-list lK -> <0> pushmark s -> <$> const(IV 2) sM -> - <1> ex-rv2cv sK/130 ->- <$> gv(*Just) s -> - <1> ex-rv2cv sK/2 ->- # mbind instead of >> <$> gv(*mbind) s -> <1> refgen K/1 -> - <1> ex-list lKRM -> <0> pushmark sRM -> <$> anoncode[CV ] lRM -> # ??? set up anon sub # my $x = shift <0> padsv[$x:2078,2080] sM/LVINTRO ->p # the next ; is moved into this new lambda! <;> nextstate(main 2079 b.pl:20) v:*,&,$ ->v
    KABOOM
  • 66. Source deparsing
    • Works surprisingly well
  • 67. Source deparsing
    • Works surprisingly well
    • for trivial cases
    • (a bit fragile)‏
  • 68. Source deparsing
    • Works surprisingly well
    • for trivial cases
    • (a bit fragile)‏
    • though localised to mdo { ... }
  • 69. Devel::Declare
    • Even nicer syntax
    • mdo { mbind $x = 1; mbind $y = 2; mbind $z = $x + $y; say “$x * $y = $z”; }
  • 70. Devel::Declare
    • And cuter implementation:
    • mdo { mbind $x = 1; mbind $y = 2; mbind $z = $x + $y; say “$x * $y = $z”; }
  • 71. Devel::Declare
    • The problem:
    • mdo { mbind 1, sub { my $x = shift; mbind 2, sub { my $y = shift; mbind $x + $y, sub { my $z = shift; say “$x * $y = $z”; } ...
  • 72. Devel::Declare
    • No need to count nesting:
    • scope_inject
    • Scope::Guard
    • Use to inject a ; at the end of method declarations:
    • method foo ($x) { print $x; } # look Ma, no semicolon!
  • 73. Devel::Declare
    • mbind's scope_inject adds a “}”
    • mdo { mbind 1, sub { my $x = shift; mbind 2, sub { my $y = shift; mbind $x + $y, sub { my $z = shift; say “$x * $y = $z”; } # adds a closing brace }
  • 74. Devel::Declare
    • mbind's scope_inject adds a “}”
    • mdo { mbind 1, sub { my $x = shift; mbind 2, sub { my $y = shift; mbind $x + $y, sub { my $z = shift; say “$x * $y = $z”; } } # adds a closing brace }
  • 75. Devel::Declare
    • mbind's scope_inject adds a “}”
    • mdo { mbind 1, sub { my $x = shift; mbind 2, sub { my $y = shift; mbind $x + $y, sub { my $z = shift; say “$x * $y = $z”; } } } # adds a closing brace }
  • 76. Devel::Declare
    • mbind's scope_inject adds a “}”
    • mdo { mbind 1, sub { my $x = shift; mbind 2, sub { my $y = shift; mbind $x + $y, sub { my $z = shift; say “$x * $y = $z”; } } } } # closes block
  • 77. So...
    • We can now sequence commands!
    • mdo { mbind $x = 1; mbind $y = 2; mbind $z = $x + $y; say “$x * $y = $z”; }
  • 78. So...
    • We can now sequence commands!
    • YAY?
  • 79. So...
    • We can now sequence commands!
    • OK, so this was big news in Haskell in 1990s
  • 80. So...
    • We can now sequence commands!
    • OK, so this was big news in Haskell in 1990s
    • Imperative languages have always done this
  • 81. What else can monads do ?
    • Sequencing
    • mdo { mbind $x = 1; mbind $y = 2; mbind $z = $x + $y; say “$x * $y = $z”; }
  • 82. What else can monads do ?
    • Sequencing
    • mdo { mbind $x = 1; mbind $y = 2; mbind $z = $x + $y; say “$x * $y = $z”; }
  • 83. What else can monads do ?
    • Sequencing
    • mdo { mbind $x = 1 ; mbind $y = 2 ; mbind $z = $x + $y ; say “$x * $y = $z”; }
  • 84. What else can monads do ?
    • Sequencing
    • mdo { mbind $x = 1 ; mbind $y = 2 ; mbind $z = $x + $y ; say “$x * $y = $z”; }
    • Programmable semicolon!
  • 85. Maybe
    • Success/Failure
    • mdo (Maybe) { mbind $FH = m_open('<', $file) ; mbind $line = <$FH> ; mbind $val = lookup(h, $line) ; say “Found $val!”; }
  • 86. Maybe
    • Success/Failure
    • mdo (Maybe) { mbind $FH = m_open('<', $file) ; mbind $line = <$FH> ; mbind $val = lookup(h, $line) ; say “Found $val!”; }
    • Will give up if can't open file, read a line from it, or look it up in a hash
  • 87. Maybe
    • Success/Failure
    • mdo (Maybe) { mbind $FH = m_open('<', $file) ; mbind $line = <$FH> ; mbind $val = lookup(h, $line) ; say “Found $val!”; }
    • Compare chain of if (foo) { if (bar) { ...
    • or eval { ... }
  • 88. Maybe $FH = open($file)‏ $line = <$FH> $val = lookup ( $line )‏ say “Found $val”
  • 89. Maybe $FH = open($file)‏ $line = <$FH> $val = lookup ( $line )‏ say “Found $val”
  • 90. Sequence
  • 91. Maybe ? ? ?
  • 92. Multiple (List)‏
  • 93. List $x = [1..10] $y = [1..10] guard $x+$y == 10 say “$x+$y=10”
  • 94. List
    • Cartesian product
    • mdo { mbind $x = [1..10] ; mbind $y = [1..10] ; mbind guard $x+$y == 10 ; say “$x+$y=10”; }
    • Run every $x against every $y and filter
  • 95. List
    • Cartesian product
    • mdo { mbind $x = [1..10] ; mbind $y = [1..10] ; mbind guard $x+$y == 10 ; say “$x+$y=10”; }
    • 1+9=10
    • 2+8=10
    • ...
  • 96. List
    • Cartesian product
    • mdo { mbind $x = [1..10] ; mbind $y = [1..10] ; mbind guard $x+$y == 10 ; say “$x+$y=10”; }
    • just like SQL
    • or LINQ
  • 97. List comprehension
    • More compact syntax
    • mcomp ($x <- [1..10]; $y <- [1..10]; $x+y==10) { say “$x+$y=10” }
  • 98. List
    • mdo { mbind $x = [1..10] ; mbind $y = [1..10] ; mbind guard $x+$y == 10; say “$x+$y=10”; }
    • We're actually calling mbind on a list
  • 99. List
    • mdo { mbind $x = [1..10] ; mbind $y = [1..10] ; mbind guard $x+$y == 10; say “$x+$y=10”; }
    • We're actually calling mbind on a list
    • autobox
  • 100. Perl++
    • Not really a functional language...
    • But you can take it surprisingly far
    • (CPAN++)‏
  • 101. What else can I do with monads?
    • Parsing
    • Error handling
    • SQL generation
    • Continuations (real resumable ones)‏
  • 102. Wants monads now!
    • Techniques are valuable now
    • Nicely wrapped implementation will be ready soon....
  • 103. Thanks!
    • questions?