Functional pe(a)rls <ul><ul><li>London Perl Workshop </li></ul></ul><ul><ul><li>29/11/2008 </li></ul></ul><ul><ul><li>vers...
A sequence <ul><li>Debolaz, on #moose </li></ul><ul><li>a list of numbers like </li></ul><ul><ul><li>10,  25,  50, </li></...
A sequence <ul><li>1.  (power of 10)     * 2.5  </li></ul><ul><li>2.  * 2 </li></ul><ul><li>3.  * 2 </li></ul>
A sequence <ul><ul><li>without tracking any other state than the number itself </li></ul></ul>
A sequence <ul><ul><li>/^1/ </li></ul></ul>
A sequence <ul><ul><li>/^1/   # power of 10 </li></ul></ul>
A sequence <ul><li>cycle [2.5, 2, 2] </li></ul>
A sequence <ul><li>cycle [2.5, 2, 2] </li></ul><ul><ul><li>2.5 </li></ul></ul><ul><ul><li>2 </li></ul></ul><ul><ul><li>2 <...
A sequence <ul><li>Oops!  </li></ul><ul><li>Perl doesn't have infinite sequences </li></ul>
A sequence <ul><ul><li>Iterators </li></ul></ul>
A sequence <ul><ul><li>curry cycle (@list) { </li></ul></ul><ul><ul><li>my @curr = @list; </li></ul></ul><ul><ul><li>retur...
A sequence <ul><li>my $c = cycle    [2.5, 2, 2]; </li></ul>
A sequence <ul><li>my $c = cycle    [2.5, 2, 2]; </li></ul><ul><ul><li>say $c->();  # 2.5 </li></ul></ul><ul><ul><li>say $...
A sequence cycle [2.5, 2, 2];
A sequence 10, cycle [2.5, 2, 2];
A sequence   mult,  10, cycle [2.5, 2, 2];
(curry)‏ <ul><ul><li>curry mult ($x,$y) {  </li></ul></ul><ul><ul><li>$x * $y  </li></ul></ul><ul><ul><li>} </li></ul></ul>
(curry)‏ <ul><ul><li>say mult( 3, 4 ); </li></ul></ul><ul><ul><li># 12 </li></ul></ul>
(curry)‏ <ul><ul><li>my $triple = mult(3); </li></ul></ul><ul><ul><li>say $triple->(10); </li></ul></ul><ul><ul><li># 30 <...
(curry)‏ <ul><ul><li>my $multiply = mult; </li></ul></ul><ul><ul><li>say $multiply->(6, 8); </li></ul></ul>
(curry)‏ <ul><ul><li>my $multiply = &mult; </li></ul></ul><ul><ul><li>my $multiply = mult; </li></ul></ul>
A sequence   mult ,  10, cycle [2.5, 2, 2];
A sequence scan    mult,  10, cycle [2.5, 2, 2];
(Scanning)‏ scan  add,  1, [2, 3, 4]; # [1, 3, 6, 10]
A sequence scan    mult,  10, cycle  [2.5, 2, 2];
A sequence take 12 =>  scan    mult,  10, cycle [2.5, 2, 2];
A sequence say for  take 12 =>  scan    mult,  10, cycle [2.5, 2, 2];
A sequence <ul><li>10 </li></ul><ul><li>25 </li></ul><ul><li>50 </li></ul><ul><li>100 </li></ul><ul><li>250 </li></ul><ul>...
How? <ul><li>Iterators (HOP)‏ </li></ul><ul><ul><li>HOP::Stream </li></ul></ul><ul><ul><li>Lazy variables </li></ul></ul>
How? <ul><li>Iterators (HOP)‏ </li></ul><ul><li>FP (scan, take)‏ </li></ul>
How? <ul><li>Iterators (HOP)‏ </li></ul><ul><li>FP (scan, take)‏ </li></ul><ul><li>Sub::Curried </li></ul>
How? <ul><li>Iterators (HOP)‏ </li></ul><ul><li>FP (scan, take)‏ </li></ul><ul><li>Sub::Curried </li></ul><ul><li>Devel::D...
Devel::Declare <ul><ul><li>curry mult ($x,$y) {  </li></ul></ul><ul><ul><li>$x * $y  </li></ul></ul><ul><ul><li>} </li></u...
Devel::Declare <ul><li>New syntax! </li></ul><ul><li>(But better than source filters)‏ </li></ul>
Devel::Declare <ul><li>New syntax! </li></ul><ul><li>(But better than source filters)‏ </li></ul><ul><ul><li>Method declar...
Devel::Declare <ul><li>New syntax! </li></ul><ul><li>(But better than source filters)‏ </li></ul><ul><ul><li>Currying </li...
Devel::Declare <ul><li>In Perl! </li></ul><ul><li>(With a bit of scary XS magic)‏ </li></ul><ul><ul><li>hooks into the com...
Some light relief
Some light relief Monads
Monads <ul><li>Come from maths </li></ul><ul><li>“ Category theory” </li></ul>
Monads <ul><li>Come from maths </li></ul><ul><li>“ Category theory” </li></ul><ul><li>Very clever people rave about them b...
Monads <ul><li>Come from maths </li></ul><ul><li>“ Category theory” </li></ul><ul><li>Very clever people rave about them b...
Monad tutorials
Monad tutorials
Monad tutorials
Monad tutorials
Monad tutorials Step 1: Write Monad Tutorial
Monad tutorials Step 2: ???
Monad tutorials Step 3: Profit!
Monads <ul><li>You already use monads </li></ul>
Monads <ul><li>You already use monads </li></ul><ul><li>YAY! </li></ul>
Monads <ul><li>You already use monads </li></ul><ul><li>Sequences of commands? </li></ul>
Sequencing my $x = 1; my $y = 2; my $z = $x * $y; say “$x * $y = $z”;
Sequencing my $x = 1; my $y = 2; my $z = $x * $y; say “$x * $y = $z”;
Sequencing my $x = 1; my $y = 2; my $z = $x * $y; say “$x * $y = $z”;
Sequencing my @seq = sub { my $x = 1 }, sub { my $y = 2 }, sub { my $z = $x * $y }, sub { say &quot;$x * $y = $z&quot;  };
Sequencing my @seq = sub { my $x = 1 }, sub { my $y = 2 }, sub { my $z = $x * $y }, sub { say &quot;$x * $y = $z&quot;  };...
Nesting my $x = 1; my $y = 2; my $z = $x * $y; say “$x * $y = $z”;
Nesting sub { my $x = 1; sub { my $y = 2; sub { my $z = $x * $y; sub { say &quot;$x * $y = $z&quot;; }->() }->() }->() }->...
Monads made pretty <ul><li>Source filters! </li></ul><ul><ul><li>http://sleepingsquirrel.org/monads/monads.html </li></ul>...
Monads made pretty <ul><li>Source filters! </li></ul><ul><ul><li>http://sleepingsquirrel.org/monads/monads.html </li></ul>...
Monads made pretty <ul><li>We want a syntax like </li></ul><ul><li>mdo {   my $x = mbind(1);   my $y = mbind(2);   my $z =...
Monads made pretty <ul><li>We want a syntax like </li></ul><ul><li>mdo {   my $x = mbind(1);   my $y = mbind(2);   my $z =...
Optree munging <ul><li>19:  my $x << Just 2; ... n  <;> nextstate(main 2078 b.pl:19) v:*,&,$ ->o t  <2> left_shift[t3] vK ...
Optree munging <ul><li>19:  my $x << Just 2; ... n  <;> nextstate(main 2078 b.pl:19) v:*,&,$ ->o t  <2> left_shift[t3] vK ...
Source deparsing <ul><li>Works surprisingly well </li></ul>
Source deparsing <ul><li>Works surprisingly well </li></ul><ul><li>for trivial cases </li></ul><ul><li>(a bit fragile)‏ </...
Source deparsing <ul><li>Works surprisingly well </li></ul><ul><li>for trivial cases </li></ul><ul><li>(a bit fragile)‏ </...
Devel::Declare <ul><li>Even nicer syntax </li></ul><ul><li>mdo {   mbind $x = 1;   mbind $y = 2;   mbind $z = $x + $y;   s...
Devel::Declare <ul><li>And cuter implementation: </li></ul><ul><li>mdo {   mbind $x = 1;   mbind $y = 2;   mbind $z = $x +...
Devel::Declare <ul><li>The problem: </li></ul><ul><li>mdo {   mbind 1, sub { my $x = shift;   mbind 2, sub { my $y = shift...
Devel::Declare <ul><li>No need to count nesting: </li></ul><ul><li>scope_inject </li></ul><ul><li>Scope::Guard </li></ul><...
Devel::Declare <ul><li>mbind's scope_inject adds a “}” </li></ul><ul><li>mdo {   mbind 1, sub { my $x = shift;   mbind 2, ...
Devel::Declare <ul><li>mbind's scope_inject adds a “}” </li></ul><ul><li>mdo {   mbind 1, sub { my $x = shift;   mbind  2,...
Devel::Declare <ul><li>mbind's scope_inject adds a “}” </li></ul><ul><li>mdo {   mbind  1, sub  {  my $x = shift;   mbind ...
Devel::Declare <ul><li>mbind's scope_inject adds a “}” </li></ul><ul><li>mdo   {   mbind 1, sub { my $x = shift;   mbind 2...
So... <ul><li>We can now sequence commands! </li></ul><ul><li>mdo {   mbind $x = 1;   mbind $y = 2;   mbind $z = $x + $y; ...
So... <ul><li>We can now sequence commands! </li></ul><ul><li>YAY? </li></ul>
So... <ul><li>We can now sequence commands! </li></ul><ul><li>OK, so this was big news in Haskell in 1990s </li></ul>
So... <ul><li>We can now sequence commands! </li></ul><ul><li>OK, so this was big news in Haskell in 1990s </li></ul><ul><...
What else can monads  do  ? <ul><li>Sequencing </li></ul><ul><li>mdo {   mbind $x = 1;   mbind $y = 2;   mbind $z = $x + $...
What else can monads  do  ? <ul><li>Sequencing </li></ul><ul><li>mdo {   mbind  $x = 1;   mbind  $y = 2;   mbind  $z = $x ...
What else can monads  do  ? <ul><li>Sequencing </li></ul><ul><li>mdo {   mbind $x = 1 ;   mbind $y = 2 ;   mbind $z = $x +...
What else can monads  do  ? <ul><li>Sequencing </li></ul><ul><li>mdo {   mbind $x = 1 ;   mbind $y = 2 ;   mbind $z = $x +...
Maybe <ul><li>Success/Failure </li></ul><ul><li>mdo (Maybe) {   mbind $FH = m_open('<', $file) ;   mbind $line = <$FH> ;  ...
Maybe <ul><li>Success/Failure </li></ul><ul><li>mdo (Maybe) {   mbind $FH = m_open('<', $file) ;   mbind $line = <$FH> ;  ...
Maybe <ul><li>Success/Failure </li></ul><ul><li>mdo (Maybe) {   mbind $FH = m_open('<', $file) ;   mbind $line = <$FH> ;  ...
Maybe $FH = open($file)‏ $line = <$FH> $val = lookup ( $line )‏ say “Found $val”
Maybe $FH = open($file)‏ $line = <$FH> $val = lookup ( $line )‏ say “Found $val”
Sequence
Maybe ? ? ?
Multiple (List)‏
List $x = [1..10] $y = [1..10] guard $x+$y == 10 say “$x+$y=10”
List <ul><li>Cartesian product </li></ul><ul><li>mdo {   mbind $x = [1..10] ;   mbind $y = [1..10] ;   mbind guard $x+$y =...
List <ul><li>Cartesian product </li></ul><ul><li>mdo {   mbind $x = [1..10] ;   mbind $y = [1..10] ;   mbind guard $x+$y =...
List <ul><li>Cartesian product </li></ul><ul><li>mdo {   mbind $x = [1..10] ;   mbind $y = [1..10] ;   mbind guard $x+$y =...
List comprehension <ul><li>More compact syntax </li></ul><ul><li>mcomp ($x <- [1..10];    $y <- [1..10];   $x+y==10)    { ...
List <ul><li>mdo {   mbind  $x =  [1..10] ;   mbind  $y =  [1..10] ;   mbind  guard $x+$y == 10;   say “$x+$y=10”; } </li>...
List <ul><li>mdo {   mbind  $x =  [1..10] ;   mbind  $y =  [1..10] ;   mbind  guard $x+$y == 10;   say “$x+$y=10”; } </li>...
Perl++ <ul><li>Not really a functional language... </li></ul><ul><li>But you can take it surprisingly far </li></ul><ul><l...
What else can I do with monads? <ul><li>Parsing </li></ul><ul><li>Error handling </li></ul><ul><li>SQL generation </li></u...
Wants monads now! <ul><li>Techniques are valuable now </li></ul><ul><li>Nicely wrapped implementation will be ready soon.....
Thanks! <ul><li>questions? </li></ul>
Upcoming SlideShare
Loading in...5
×

Functional Pe(a)rls version 2

2,210

Published on

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/ )

Published in: Technology
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
2,210
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
41
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

Functional Pe(a)rls version 2

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

    Clipping is a handy way to collect important slides you want to go back to later.

×