osfameron Functional Pe(a)rls
Functional pe(a)rls World tour! IPW 2008 LPW 2008 NWE.pm May 2009 YAPC::EU Lisbon 2009 version 4 Osfameron
Functional Programming What is it?
Functional Programming About functions?
Functional Programming About  functions? (like Object-oriented is about objects?)
Functional Programming everything's a function!
Functional Programming 1 + 2
Functional Programming 1 + 2 Spot the  function?
Functional Programming 1 + 2 Spot the  function?
Functional Programming 1 + 2 first class?
Functional Programming 1 + 2 +
Functional Programming 1 + 2 op<+>
OPERATORS UNITE! STOP this discrimation now!
What now? <ul><li>Protest!
Cry!
Steal from Haskell! </li></ul>
What now? <ul><li>Steal from Haskell!
(+)  ← ref to add </li></ul>
Wrapping operators <ul><li>sub op ($op) {   return    sub  ($left, $right)  {   eval  “$left $op $right” ;   }; } </li></ul>
Wrapping operators <ul><li>my $add = op('+');
$add->(1, 2); # 3 </li></ul>
YAY!
YAY? <ul><li>Still uglier than Haskell </li><ul><li>(+)
op('+') </li></ul></ul>
Devel::Declare <ul><li>New syntax!
(But better than source filters) </li></ul>
Devel::Declare <ul><li>New syntax!
(But better than source filters) </li><ul><li>Method declaration
MooseX::Declare
Sub::Auto </li></ul></ul>
Sub::Section <ul><li>on github
Gives nice syntax, using  Devel::Declare
op (+) </li></ul>
Sub::Section <ul><li>on github
Gives nice syntax, using  Devel::Declare
op   (Bwahaha!)  (+) </li></ul>Devel::Declare  custom parser hook can inject code etc.
Sub::Section <ul><li>on github
Gives nice syntax, using  Devel::Declare
op   (Bwahaha!)  ('+') </li></ul>
Sub::Section <ul><li>on github
Gives nice syntax, using  Devel::Declare
Op ('+')  # Perl is none the wiser </li></ul>Tee hee!
Devel::Declare <ul><li>In Perl!
(With a bit of scary XS magic) </li><ul><li>hooks into the compiler
changing the source as you compile
horrible perl tricks to get methods installed, and braces closed
mst++, rafl++ </li></ul></ul>
Sections
Sections <ul><li>(+) isn't really a section </li></ul>
Sections <ul><li>(+) isn't really a section
(+1) is </li></ul>
Sections <ul><li>(+)  10, 5  # 15
(+1) 8  #  9 </li></ul>
Currying <ul><li>Partial application </li></ul>
Currying <ul><li>Partial application
1 arg at a time </li></ul>
Currying <ul><li>sub add ($left, $right) { return $left + $right; } </li></ul>
Currying <ul><li>sub add ($left, $right) { return $left + $right; }
(That's 2 arguments) </li></ul>
Curried functions <ul><li>sub add ($left, $right) { return $left + $right; }
(That's 2 arguments)
add(5)  ... </li></ul>
Curried functions <ul><li>sub add ($left, $right) { return $left + $right; }
(That's 2 arguments)
add(5)  # $left is bound to 5 </li></ul>
Curried functions <ul><li>sub add ($left, $right) { return $left + $right; }
(That's 2 arguments)
add(5)  # $left is bound to 5  ->(6);  # 11 </li></ul>
Implement in Perl <ul><li>Quite simple to do with closures:
sub add { my $left = shift; return sub { my $right = shift; return $left + $right; } } </li></ul>
Implement in Perl <ul><li>Quite simple to do with closures:
sub add { my $left = shift; return sub { my $right = shift; return $left + $right; } }
Not pretty or convenient though </li></ul>
Sub::Curried <ul><li>on CPAN
Gives nice syntax, using  Devel::Declare
sub  add ($left, $right) { return $left + $right; } </li></ul>
Sub::Curried <ul><li>on CPAN
Gives nice syntax, using  Devel::Declare
curry  add ($left, $right) { return $left + $right; } </li></ul>
Sub::Curried <ul><li>on CPAN
Gives nice syntax, using  Devel::Declare
curry   (bwahaha!)   add ($left, $right) { return $left + $right; } </li></ul>
Sub::Curried <ul><li>Turn into something like
curry add { return ROUTINE unless @_; check_args(2, @_);  my $f = sub { my $f = sub { ... } $f = $f->(shift) for @_; retur...
Sub::Curried <ul><li>Turn into something like
curry add { return  ROUTINE unless @_ ; check_args(2, @_);  my $f = sub { my $f = sub { ... } $f = $f->(shift) for @_; ret...
Sub::Curried <ul><li>add(5,6);  # 11 </li></ul>
Sub::Curried <ul><li>add(5,6);  # 11
add(5);  # function that adds 5 </li></ul>
Sub::Curried <ul><li>add(5,6);  # 11
add(5);  # function that adds 5
add();  # function that adds... </li></ul>
Sub::Curried <ul><li>add(5,6);  # 11
add(5);  # function that adds 5
add();  # function that adds...
i.e =  &add </li></ul>
Sub::Curried <ul><li>Turn into something like
curry add { return ROUTINE unless @_; check_args(2 , @_);  my $f = sub { my $f = sub { ... } $f = $f->(shift) for @_; retu...
Sub::Curried <ul><li>Give diagnostics if called with too many arguments </li></ul>
Sub::Curried <ul><li>Turn into something like
curry add { return ROUTINE unless @_; check_args(2, @_);  my $f = sub { my $f = sub { ... } $f = $f->(shift) for @_; retur...
Sub::Curried <ul><li>Handle </li><ul><li>add(1,2)
add(1)->(2) </li></ul></ul>
Why? <ul><li>Partial application </li></ul>
Why? <ul><li>Automatic partial application everywhere </li></ul>
Why? <ul><li>Automatic partial application everywhere
... turns out to be useful/elegant in Haskell </li></ul>
Why? <ul><li>Automatic partial application everywhere
... turns out to be useful/elegant in Haskell
(actually, similar techniques  are  used in Perl) </li></ul>
Currying the Invocant <ul><li>package My::Class use base 'Class::Accessor'; __PACKAGE__->add_accessor('foo'); __PACKAGE__-...
Currying the Invocant <ul><li>package My::Class use base 'Class::Accessor'; My::Class ->add_accessor('foo'); My::Class ->a...
Currying the Invocant <ul><li>package My::Class use base 'Class::Accessor'; My::Class ->add_accessor('foo'); My::Class ->a...
sub add_accessor { my ( $self , $accessor) = @_; .... </li></ul>
Currying the Invocant <ul><li>Perl importing </li><ul><li>*{$CALLER::has} = &has; </li></ul></ul>
Currying the Invocant <ul><li>Perl importing </li><ul><li>*{$CALLER::has} = &has;
*{$CALLER::has} = mk_has(); </li></ul></ul>
Currying the Invocant <ul><li>Perl importing </li><ul><li>*{$CALLER::has} = &has;
*{$CALLER::has} = mk_has();
*{$CALLER::has} = has($CALLER); </li></ul></ul>
Currying the Invocant <ul><li>Moose! </li><ul><li>package My::Class; use Moose;  # imports has=has('My::Class') has 'foo';...
Currying the Invocant <ul><li>Moose! </li><ul><li>package My::Class; use Moose;  # imports has=has('My::Class') has 'foo';...
Where were we? <ul><li>my $add = +;  # FAIL </li></ul>
Where were we? <ul><li>my $add = +;  # FAIL
my $add = op(+);  # YAY </li></ul>
Where were we? <ul><li>my $add = +;  # FAIL
my $add = op(+);  # YAY
my $add2 = op(+2);   # take THAT, Haskell! </li></ul>
But... <ul><li>(-1) </li></ul>
But... <ul><li>(-1)
(1-) </li></ul>
But... <ul><li>(-1)
(1-)  # minus(1) </li></ul>
But... <ul><li>(-1)  # minus(???)->(1)
(1-)  # minus(1) </li></ul>
But... <ul><li>(-1)  # (flip(minus))->(1)
(1-)  # minus(1) </li></ul>
Flip <ul><li>curry flip ($fn, $left, $right) { $fn->($right, $left); } </li></ul>
Flip <ul><li>curry flip ($fn,  $left, $right ) { $fn->($right, $left); }
Minus  (3, 1)  # 2
flip(minus)->(3, 1)  # -2; </li></ul>
Flip <ul><li>…  and with currying
my $prev = flip(minus)->(1);
$prev->( 5 ); </li><ul><li>$left  = 1
$right = 5
minus($right=5, $left=1); # 4 </li></ul></ul>
Sub::Section <ul><li>More cool stuff </li></ul>
Sub::Section <ul><li>my $greet = op(“Hello ” .); </li></ul>
Sub::Section <ul><li>my $greet = op(“Hello ” .);
$greet->(“World”); # “Hello World” </li></ul>
Sub::Section <ul><li>map op(*2), @numbers; </li><ul><li>(1,2,3,4)
> (2,4,6,8) </li></ul></ul>
Sub::Section <ul><li>map op(*2), @numbers; </li><ul><li>(1,2,3,4)
> (2,4,6,8) </li></ul></ul>
Sub::Section <ul><li>Perl map doesn't take functions... </li></ul>
Sub::Section <ul><li>Perl map doesn't take functions...
map op(*2) ->($_) , @numbers; </li><ul><li>(1,2,3,4)
> (2,4,6,8) </li></ul></ul>
(rant) <ul><li>Perl's map is not functional </li></ul>
(rant) <ul><li>Perl's map is not functional </li><ul><li>We took a feature from FP...  and made it not take functions. </l...
(rant) <ul><li>Perl's map is not functional
Perl's $_ is a horrible hack around not doing currying properly </li></ul>
(rant) <ul><li>Perl's map is not functional
Perl's $_ is a horrible hack around not doing currying properly
Why am I still programming this silly language? ;-) </li></ul>
(yay!) <ul><li>Perl's map is not functional
Perl's $_ is a horrible hack around not doing currying properly
Why am I still programming this silly language? ;-)
Oh yes! - because I can change it. </li></ul>
TODO:  Functional::Map <ul><li>fmap &some_func, @list;
fmap sub { … },  @list;
fmap op(+2),  @list; </li></ul>
TODO:  Functional::Map <ul><li>fmap &some_func, @list;
fmap sub { … },  @list;
fmap op(+2),  @list;
(those will all work anyway) </li></ul>
TODO:  Functional::Map <ul><li>fmap &some_func, @list;
fmap sub { … },  @list;
fmap op(+2),  @list;
(those will all work anyway)
fmap { uc } @list; </li></ul>
TODO:  Functional::Map <ul><li>fmap &some_func, @list;
fmap sub { … },  @list;
fmap op(+2),  @list;
Upcoming SlideShare
Loading in …5
×

Functional Pearls 4 (YAPC::EU::2009 remix)

2,143
-1

Published on

The YAPC::EU::2009 (Lisbon) remix of my Functional Pe(a)rls talk.

Published in: Technology, Business
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

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

No notes for slide

Functional Pearls 4 (YAPC::EU::2009 remix)

  1. 1. osfameron Functional Pe(a)rls
  2. 2. Functional pe(a)rls World tour! IPW 2008 LPW 2008 NWE.pm May 2009 YAPC::EU Lisbon 2009 version 4 Osfameron
  3. 3. Functional Programming What is it?
  4. 4. Functional Programming About functions?
  5. 5. Functional Programming About functions? (like Object-oriented is about objects?)
  6. 6. Functional Programming everything's a function!
  7. 7. Functional Programming 1 + 2
  8. 8. Functional Programming 1 + 2 Spot the function?
  9. 9. Functional Programming 1 + 2 Spot the function?
  10. 10. Functional Programming 1 + 2 first class?
  11. 11. Functional Programming 1 + 2 +
  12. 12. Functional Programming 1 + 2 op<+>
  13. 13. OPERATORS UNITE! STOP this discrimation now!
  14. 14. What now? <ul><li>Protest!
  15. 15. Cry!
  16. 16. Steal from Haskell! </li></ul>
  17. 17. What now? <ul><li>Steal from Haskell!
  18. 18. (+) ← ref to add </li></ul>
  19. 19. Wrapping operators <ul><li>sub op ($op) { return sub ($left, $right) { eval “$left $op $right” ; }; } </li></ul>
  20. 20. Wrapping operators <ul><li>my $add = op('+');
  21. 21. $add->(1, 2); # 3 </li></ul>
  22. 22. YAY!
  23. 23. YAY? <ul><li>Still uglier than Haskell </li><ul><li>(+)
  24. 24. op('+') </li></ul></ul>
  25. 25. Devel::Declare <ul><li>New syntax!
  26. 26. (But better than source filters) </li></ul>
  27. 27. Devel::Declare <ul><li>New syntax!
  28. 28. (But better than source filters) </li><ul><li>Method declaration
  29. 29. MooseX::Declare
  30. 30. Sub::Auto </li></ul></ul>
  31. 31. Sub::Section <ul><li>on github
  32. 32. Gives nice syntax, using Devel::Declare
  33. 33. op (+) </li></ul>
  34. 34. Sub::Section <ul><li>on github
  35. 35. Gives nice syntax, using Devel::Declare
  36. 36. op (Bwahaha!) (+) </li></ul>Devel::Declare custom parser hook can inject code etc.
  37. 37. Sub::Section <ul><li>on github
  38. 38. Gives nice syntax, using Devel::Declare
  39. 39. op (Bwahaha!) ('+') </li></ul>
  40. 40. Sub::Section <ul><li>on github
  41. 41. Gives nice syntax, using Devel::Declare
  42. 42. Op ('+') # Perl is none the wiser </li></ul>Tee hee!
  43. 43. Devel::Declare <ul><li>In Perl!
  44. 44. (With a bit of scary XS magic) </li><ul><li>hooks into the compiler
  45. 45. changing the source as you compile
  46. 46. horrible perl tricks to get methods installed, and braces closed
  47. 47. mst++, rafl++ </li></ul></ul>
  48. 48. Sections
  49. 49. Sections <ul><li>(+) isn't really a section </li></ul>
  50. 50. Sections <ul><li>(+) isn't really a section
  51. 51. (+1) is </li></ul>
  52. 52. Sections <ul><li>(+) 10, 5 # 15
  53. 53. (+1) 8 # 9 </li></ul>
  54. 54. Currying <ul><li>Partial application </li></ul>
  55. 55. Currying <ul><li>Partial application
  56. 56. 1 arg at a time </li></ul>
  57. 57. Currying <ul><li>sub add ($left, $right) { return $left + $right; } </li></ul>
  58. 58. Currying <ul><li>sub add ($left, $right) { return $left + $right; }
  59. 59. (That's 2 arguments) </li></ul>
  60. 60. Curried functions <ul><li>sub add ($left, $right) { return $left + $right; }
  61. 61. (That's 2 arguments)
  62. 62. add(5) ... </li></ul>
  63. 63. Curried functions <ul><li>sub add ($left, $right) { return $left + $right; }
  64. 64. (That's 2 arguments)
  65. 65. add(5) # $left is bound to 5 </li></ul>
  66. 66. Curried functions <ul><li>sub add ($left, $right) { return $left + $right; }
  67. 67. (That's 2 arguments)
  68. 68. add(5) # $left is bound to 5 ->(6); # 11 </li></ul>
  69. 69. Implement in Perl <ul><li>Quite simple to do with closures:
  70. 70. sub add { my $left = shift; return sub { my $right = shift; return $left + $right; } } </li></ul>
  71. 71. Implement in Perl <ul><li>Quite simple to do with closures:
  72. 72. sub add { my $left = shift; return sub { my $right = shift; return $left + $right; } }
  73. 73. Not pretty or convenient though </li></ul>
  74. 74. Sub::Curried <ul><li>on CPAN
  75. 75. Gives nice syntax, using Devel::Declare
  76. 76. sub add ($left, $right) { return $left + $right; } </li></ul>
  77. 77. Sub::Curried <ul><li>on CPAN
  78. 78. Gives nice syntax, using Devel::Declare
  79. 79. curry add ($left, $right) { return $left + $right; } </li></ul>
  80. 80. Sub::Curried <ul><li>on CPAN
  81. 81. Gives nice syntax, using Devel::Declare
  82. 82. curry (bwahaha!) add ($left, $right) { return $left + $right; } </li></ul>
  83. 83. Sub::Curried <ul><li>Turn into something like
  84. 84. curry add { return ROUTINE unless @_; check_args(2, @_); my $f = sub { my $f = sub { ... } $f = $f->(shift) for @_; return $f; } </li></ul>
  85. 85. Sub::Curried <ul><li>Turn into something like
  86. 86. curry add { return ROUTINE unless @_ ; check_args(2, @_); my $f = sub { my $f = sub { ... } $f = $f->(shift) for @_; return $f; } </li></ul>
  87. 87. Sub::Curried <ul><li>add(5,6); # 11 </li></ul>
  88. 88. Sub::Curried <ul><li>add(5,6); # 11
  89. 89. add(5); # function that adds 5 </li></ul>
  90. 90. Sub::Curried <ul><li>add(5,6); # 11
  91. 91. add(5); # function that adds 5
  92. 92. add(); # function that adds... </li></ul>
  93. 93. Sub::Curried <ul><li>add(5,6); # 11
  94. 94. add(5); # function that adds 5
  95. 95. add(); # function that adds...
  96. 96. i.e = &add </li></ul>
  97. 97. Sub::Curried <ul><li>Turn into something like
  98. 98. curry add { return ROUTINE unless @_; check_args(2 , @_); my $f = sub { my $f = sub { ... } $f = $f->(shift) for @_; return $f; } </li></ul>
  99. 99. Sub::Curried <ul><li>Give diagnostics if called with too many arguments </li></ul>
  100. 100. Sub::Curried <ul><li>Turn into something like
  101. 101. curry add { return ROUTINE unless @_; check_args(2, @_); my $f = sub { my $f = sub { ... } $f = $f->(shift) for @_; return $f; } </li></ul>
  102. 102. Sub::Curried <ul><li>Handle </li><ul><li>add(1,2)
  103. 103. add(1)->(2) </li></ul></ul>
  104. 104. Why? <ul><li>Partial application </li></ul>
  105. 105. Why? <ul><li>Automatic partial application everywhere </li></ul>
  106. 106. Why? <ul><li>Automatic partial application everywhere
  107. 107. ... turns out to be useful/elegant in Haskell </li></ul>
  108. 108. Why? <ul><li>Automatic partial application everywhere
  109. 109. ... turns out to be useful/elegant in Haskell
  110. 110. (actually, similar techniques are used in Perl) </li></ul>
  111. 111. Currying the Invocant <ul><li>package My::Class use base 'Class::Accessor'; __PACKAGE__->add_accessor('foo'); __PACKAGE__->add_accessor('bar'); __PACKAGE__->add_accessor('baz'); </li></ul>
  112. 112. Currying the Invocant <ul><li>package My::Class use base 'Class::Accessor'; My::Class ->add_accessor('foo'); My::Class ->add_accessor('bar'); My::Class ->add_accessor('baz'); </li></ul>
  113. 113. Currying the Invocant <ul><li>package My::Class use base 'Class::Accessor'; My::Class ->add_accessor('foo'); My::Class ->add_accessor('bar'); My::Class ->add_accessor('baz');
  114. 114. sub add_accessor { my ( $self , $accessor) = @_; .... </li></ul>
  115. 115. Currying the Invocant <ul><li>Perl importing </li><ul><li>*{$CALLER::has} = &has; </li></ul></ul>
  116. 116. Currying the Invocant <ul><li>Perl importing </li><ul><li>*{$CALLER::has} = &has;
  117. 117. *{$CALLER::has} = mk_has(); </li></ul></ul>
  118. 118. Currying the Invocant <ul><li>Perl importing </li><ul><li>*{$CALLER::has} = &has;
  119. 119. *{$CALLER::has} = mk_has();
  120. 120. *{$CALLER::has} = has($CALLER); </li></ul></ul>
  121. 121. Currying the Invocant <ul><li>Moose! </li><ul><li>package My::Class; use Moose; # imports has=has('My::Class') has 'foo'; has 'bar'; has 'baz'; </li></ul></ul>
  122. 122. Currying the Invocant <ul><li>Moose! </li><ul><li>package My::Class; use Moose; # imports has=has('My::Class') has 'foo'; has 'bar'; has 'baz'; </li></ul><li>(handwave) </li></ul>
  123. 123. Where were we? <ul><li>my $add = +; # FAIL </li></ul>
  124. 124. Where were we? <ul><li>my $add = +; # FAIL
  125. 125. my $add = op(+); # YAY </li></ul>
  126. 126. Where were we? <ul><li>my $add = +; # FAIL
  127. 127. my $add = op(+); # YAY
  128. 128. my $add2 = op(+2); # take THAT, Haskell! </li></ul>
  129. 129. But... <ul><li>(-1) </li></ul>
  130. 130. But... <ul><li>(-1)
  131. 131. (1-) </li></ul>
  132. 132. But... <ul><li>(-1)
  133. 133. (1-) # minus(1) </li></ul>
  134. 134. But... <ul><li>(-1) # minus(???)->(1)
  135. 135. (1-) # minus(1) </li></ul>
  136. 136. But... <ul><li>(-1) # (flip(minus))->(1)
  137. 137. (1-) # minus(1) </li></ul>
  138. 138. Flip <ul><li>curry flip ($fn, $left, $right) { $fn->($right, $left); } </li></ul>
  139. 139. Flip <ul><li>curry flip ($fn, $left, $right ) { $fn->($right, $left); }
  140. 140. Minus (3, 1) # 2
  141. 141. flip(minus)->(3, 1) # -2; </li></ul>
  142. 142. Flip <ul><li>… and with currying
  143. 143. my $prev = flip(minus)->(1);
  144. 144. $prev->( 5 ); </li><ul><li>$left = 1
  145. 145. $right = 5
  146. 146. minus($right=5, $left=1); # 4 </li></ul></ul>
  147. 147. Sub::Section <ul><li>More cool stuff </li></ul>
  148. 148. Sub::Section <ul><li>my $greet = op(“Hello ” .); </li></ul>
  149. 149. Sub::Section <ul><li>my $greet = op(“Hello ” .);
  150. 150. $greet->(“World”); # “Hello World” </li></ul>
  151. 151. Sub::Section <ul><li>map op(*2), @numbers; </li><ul><li>(1,2,3,4)
  152. 152. > (2,4,6,8) </li></ul></ul>
  153. 153. Sub::Section <ul><li>map op(*2), @numbers; </li><ul><li>(1,2,3,4)
  154. 154. > (2,4,6,8) </li></ul></ul>
  155. 155. Sub::Section <ul><li>Perl map doesn't take functions... </li></ul>
  156. 156. Sub::Section <ul><li>Perl map doesn't take functions...
  157. 157. map op(*2) ->($_) , @numbers; </li><ul><li>(1,2,3,4)
  158. 158. > (2,4,6,8) </li></ul></ul>
  159. 159. (rant) <ul><li>Perl's map is not functional </li></ul>
  160. 160. (rant) <ul><li>Perl's map is not functional </li><ul><li>We took a feature from FP... and made it not take functions. </li></ul></ul>
  161. 161. (rant) <ul><li>Perl's map is not functional
  162. 162. Perl's $_ is a horrible hack around not doing currying properly </li></ul>
  163. 163. (rant) <ul><li>Perl's map is not functional
  164. 164. Perl's $_ is a horrible hack around not doing currying properly
  165. 165. Why am I still programming this silly language? ;-) </li></ul>
  166. 166. (yay!) <ul><li>Perl's map is not functional
  167. 167. Perl's $_ is a horrible hack around not doing currying properly
  168. 168. Why am I still programming this silly language? ;-)
  169. 169. Oh yes! - because I can change it. </li></ul>
  170. 170. TODO: Functional::Map <ul><li>fmap &some_func, @list;
  171. 171. fmap sub { … }, @list;
  172. 172. fmap op(+2), @list; </li></ul>
  173. 173. TODO: Functional::Map <ul><li>fmap &some_func, @list;
  174. 174. fmap sub { … }, @list;
  175. 175. fmap op(+2), @list;
  176. 176. (those will all work anyway) </li></ul>
  177. 177. TODO: Functional::Map <ul><li>fmap &some_func, @list;
  178. 178. fmap sub { … }, @list;
  179. 179. fmap op(+2), @list;
  180. 180. (those will all work anyway)
  181. 181. fmap { uc } @list; </li></ul>
  182. 182. TODO: Functional::Map <ul><li>fmap &some_func, @list;
  183. 183. fmap sub { … }, @list;
  184. 184. fmap op(+2), @list;
  185. 185. (those will all work anyway)
  186. 186. fmap (bwahahaha!) { uc } @list; </li></ul>
  187. 187. TODO: Functional::Map <ul><li>fmap &some_func, @list;
  188. 188. fmap sub { … }, @list;
  189. 189. fmap op(+2), @list;
  190. 190. (those will all work anyway)
  191. 191. fmap sub { uc } , @list; </li></ul>
  192. 192. TODO: Functional::Map <ul><li>fmap &some_func, @list;
  193. 193. fmap sub { … }, @list;
  194. 194. fmap op(+2), @list;
  195. 195. (those will all work anyway)
  196. 196. fmap underscorify( sub { uc } ) , @list; </li></ul>
  197. 197. TODO: Functional::Map <ul><li>Dear lazyYAPC... </li></ul>
  198. 198. Sub::Section <ul><li>my $contains_foo = op(=~/foo/); </li></ul>
  199. 199. More complex examples <ul><li>centigrade = (fahrenheit-32)*5/9 </li></ul>
  200. 200. More complex examples <ul><li>centigrade = (fahrenheit-32)*5/9
  201. 201. my $f2c = sub { op(*5/9)->( op(-32)->(shift)) }; </li></ul>
  202. 202. More complex examples <ul><li>centigrade = (fahrenheit-32)*5/9
  203. 203. my $f2c = sub { op(*5/9)->( op(-32)->(shift)) };
  204. 204. MY EYES! </li></ul>
  205. 205. More complex examples <ul><li>centigrade = (fahrenheit-32)*5/9
  206. 206. my $f2c = sub { op(*5/9) ->( op(-32) ->(shift)) }; </li></ul>
  207. 207. More complex examples <ul><li>centigrade = (fahrenheit-32)*5/9
  208. 208. my $f2c = sub { op(*5/9) ->( op(-32) ->(shift)) };
  209. 209. Never mind the boilerplate... </li></ul>
  210. 210. More complex examples <ul><li>centigrade = (fahrenheit-32)*5/9
  211. 211. my $f2c = op(*5/9) << op(-32)
  212. 212. Composition </li></ul>
  213. 213. More complex examples <ul><li>centigrade = (fahrenheit-32)*5/9
  214. 214. my $f2c = op(*5/9) << op(-32)
  215. 215. Sub::Compose </li></ul>
  216. 216. More complex examples <ul><li>centigrade = (fahrenheit-32)*5/9
  217. 217. my $f2c = op(*5/9) << op(-32)
  218. 218. Sub::Compose </li><ul><li>base class for Sub::Curried, Sub::Section </li></ul></ul>
  219. 219. More complex examples <ul><li>centigrade = (fahrenheit-32)*5/9
  220. 220. my $f2c = op(*5/9) << op(-32)
  221. 221. Sub::Compose </li><ul><li>base class for Sub::Curried, Sub::Section
  222. 222. ... autobox? </li></ul></ul>
  223. 223. Point-free! <ul><li>Or point less programming
  224. 224. (obfu for maths types) </li></ul>
  225. 225. Point-free! <ul><li>my $square = op(*) << dup;
  226. 226. $square->(4); # 16 </li></ul>
  227. 227. Point-free! <ul><li>curry dup ($arg) { ($arg)x 2 }
  228. 228. my $square = op(*) << dup;
  229. 229. $square->(4); # 16 </li></ul>
  230. 230. Point-free! <ul><li>curry dup ($arg) { ($arg)x 2 }
  231. 231. my $dup = op(x 2); # ? </li></ul>
  232. 232. Point-free! <ul><li>curry dup ($arg) { ($arg)x 2 }
  233. 233. my $dup = op(x 2); “$arg$arg” </li></ul>
  234. 234. Point-free! <ul><li>curry dup ($arg) { ($arg)x 2 }
  235. 235. my $dup = op(x 2); “$arg$arg” </li><ul><li>TODO: alternate syntax for list context:
  236. 236. op[x 2] # thanks mst </li></ul></ul>
  237. 237. Some light relief
  238. 238. Some light relief Monads
  239. 239. Monads <ul><li>Come from maths
  240. 240. “Category theory” </li></ul>
  241. 241. Monads <ul><li>Come from maths
  242. 242. “Category theory”
  243. 243. Very clever people rave about them being useful </li></ul>
  244. 244. Monads <ul><li>Come from maths
  245. 245. “Category theory”
  246. 246. Very clever people rave about them being useful
  247. 247. Have a reputation for being hard to understand </li></ul>
  248. 248. Monad tutorials
  249. 249. Monad tutorials
  250. 250. Monad tutorials
  251. 251. Monad tutorials
  252. 252. Monad tutorials Step 1: Write Monad Tutorial
  253. 253. Monad tutorials Step 2: ???
  254. 254. Monad tutorials Step 3: Profit!
  255. 255. Monads <ul><li>You already use monads </li></ul>
  256. 256. Monads <ul><li>You already use monads
  257. 257. YAY! </li></ul>
  258. 258. Monads <ul><li>You already use monads
  259. 259. Sequences of commands? </li></ul>
  260. 260. Sequencing my $x = 1; my $y = 2; my $z = $x * $y; say “$x * $y = $z”;
  261. 261. Sequencing my $x = 1; my $y = 2; my $z = $x * $y; say “$x * $y = $z”;
  262. 262. Sequencing my $x = 1; my $y = 2; my $z = $x * $y; say “$x * $y = $z”;
  263. 263. Sequencing my @seq = sub { my $x = 1 }, sub { my $y = 2 }, sub { my $z = $x * $y }, sub { say &quot;$x * $y = $z&quot; };
  264. 264. 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 ...
  265. 265. Nesting my $x = 1; my $y = 2; my $z = $x * $y; say “$x * $y = $z”;
  266. 266. Nesting sub { my $x = 1; sub { my $y = 2; sub { my $z = $x * $y; sub { say &quot;$x * $y = $z&quot;; }->() }->() }->() }->();
  267. 267. Monadic programming is impractical in Perl... only because of syntactic issues – Mark Jason Dominus http://perl.plover.com/classes/fp/samples/slide027.html
  268. 268. Monads made pretty <ul><li>Source filters! </li><ul><li>http://sleepingsquirrel.org/monads/monads.html </li></ul></ul>
  269. 269. Monads made pretty <ul><li>Source filters! </li><ul><li>http://sleepingsquirrel.org/monads/monads.html </li></ul><li>Source tree manipulation (B::OP magic)
  270. 270. Deparse and source text munging </li></ul>
  271. 271. Monads made pretty <ul><li>We want a syntax like
  272. 272. mdo { my $x = mbind(1); my $y = mbind(2); my $z = mbind($x + $y); say “$x * $y = $z”; } </li></ul>
  273. 273. Monads made pretty <ul><li>We want a syntax like
  274. 274. mdo { my $x = mbind(1); my $y = mbind(2); my $z = mbind($x + $y); say “$x * $y = $z”; }
  275. 275. mdo introduces the block
  276. 276. mbind gives us a hook to rotate around </li></ul>
  277. 277. 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>
  278. 278. 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
  279. 279. Source deparsing <ul><li>Works surprisingly well </li></ul>
  280. 280. Source deparsing <ul><li>Works surprisingly well
  281. 281. for trivial cases
  282. 282. (a bit fragile) </li></ul>
  283. 283. Source deparsing <ul><li>Works surprisingly well
  284. 284. for trivial cases
  285. 285. (a bit fragile)
  286. 286. though localised to mdo { ... } </li></ul>
  287. 287. Devel::Declare <ul><li>Even nicer syntax
  288. 288. mdo { mbind $x = 1; mbind $y = 2; mbind $z = $x + $y; say “$x * $y = $z”; } </li></ul>
  289. 289. Devel::Declare <ul><li>And cuter implementation:
  290. 290. mdo { mbind $x = 1; mbind $y = 2; mbind $z = $x + $y; say “$x * $y = $z”; } </li></ul>
  291. 291. Devel::Declare <ul><li>The problem:
  292. 292. 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>
  293. 293. Devel::Declare <ul><li>No need to count nesting:
  294. 294. scope_inject
  295. 295. B::Hooks::EndOfScope
  296. 296. Use to inject a ; at the end of method declarations:
  297. 297. method foo ($x) { print $x; } # look Ma, no semicolon! </li></ul>
  298. 298. Devel::Declare <ul><li>mbind's scope_inject adds a “}”
  299. 299. 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>
  300. 300. Devel::Declare <ul><li>mbind's scope_inject adds a “}”
  301. 301. 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>
  302. 302. Devel::Declare <ul><li>mbind's scope_inject adds a “}”
  303. 303. 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>
  304. 304. Devel::Declare <ul><li>mbind's scope_inject adds a “}”
  305. 305. 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>
  306. 306. So... <ul><li>We can now sequence commands!
  307. 307. mdo { mbind $x = 1; mbind $y = 2; mbind $z = $x + $y; say “$x * $y = $z”; } </li></ul>
  308. 308. So... <ul><li>We can now sequence commands!
  309. 309. in pure Perl! </li></ul>
  310. 310. So... <ul><li>OK, so this was big news in Haskell in 1990s </li></ul>
  311. 311. So... <ul><li>OK, so this was big news in Haskell in 1990s
  312. 312. Imperative languages have always done this </li></ul>
  313. 313. What else can monads do ? <ul><li>Sequencing
  314. 314. mdo { mbind $x = 1; mbind $y = 2; mbind $z = $x + $y; say “$x * $y = $z”; } </li></ul>
  315. 315. What else can monads do ? <ul><li>Sequencing
  316. 316. mdo { mbind $x = 1; mbind $y = 2; mbind $z = $x + $y; say “$x * $y = $z”; } </li></ul>
  317. 317. What else can monads do ? <ul><li>Sequencing
  318. 318. mdo { mbind $x = 1 ; mbind $y = 2 ; mbind $z = $x + $y ; say “$x * $y = $z”; } </li></ul>
  319. 319. What else can monads do ? <ul><li>Sequencing
  320. 320. mdo { mbind $x = 1 ; mbind $y = 2 ; mbind $z = $x + $y ; say “$x * $y = $z”; }
  321. 321. Programmable semicolon! </li></ul>
  322. 322. Maybe <ul><li>Success/Failure
  323. 323. mdo (Maybe) { mbind $FH = m_open('<', $file) ; mbind $line = <$FH> ; mbind $val = lookup(h, $line) ; say “Found $val!”; } </li></ul>
  324. 324. Maybe <ul><li>Success/Failure
  325. 325. mdo (Maybe) { mbind $FH = m_open('<', $file) ; mbind $line = <$FH> ; mbind $val = lookup(h, $line) ; say “Found $val!”; }
  326. 326. Will give up if can't open file, read a line from it, or look it up in a hash </li></ul>
  327. 327. Maybe <ul><li>Success/Failure
  328. 328. mdo (Maybe) { mbind $FH = m_open('<', $file) ; mbind $line = <$FH> ; mbind $val = lookup(h, $line) ; say “Found $val!”; }
  329. 329. Compare chain of if (foo) { if (bar) { ...
  330. 330. or eval { ... } </li></ul>
  331. 331. Maybe $FH = open($file) $line = <$FH> $val = lookup ( $line ) say “Found $val”
  332. 332. Maybe $FH = open($file) $line = <$FH> $val = lookup ( $line ) say “Found $val” ?
  333. 333. Sequence
  334. 334. Maybe ? ? ?
  335. 335. Multiple (List)
  336. 336. List $x = [1..10] $y = [1..10] guard $x+$y == 10 say “$x+$y=10”
  337. 337. List <ul><li>Cartesian product
  338. 338. mdo { mbind $x = [1..10] ; mbind $y = [1..10] ; mbind guard $x+$y == 10 ; say “$x+$y=10”; }
  339. 339. Run every $x against every $y and filter </li></ul>
  340. 340. List <ul><li>Cartesian product
  341. 341. mdo { mbind $x = [1..10] ; mbind $y = [1..10] ; mbind guard $x+$y == 10 ; say “$x+$y=10”; }
  342. 342. 1+9=10
  343. 343. 2+8=10
  344. 344. ... </li></ul>
  345. 345. List <ul><li>Cartesian product
  346. 346. mdo { mbind $x = [1..10] ; mbind $y = [1..10] ; mbind guard $x+$y == 10 ; say “$x+$y=10”; }
  347. 347. just like SQL
  348. 348. or LINQ </li></ul>
  349. 349. List comprehension <ul><li>More compact syntax
  350. 350. mcomp ($x <- [1..10]; $y <- [1..10]; $x+y==10) { say “$x+$y=10” } </li></ul>
  351. 351. List <ul><li>mdo { mbind $x = [1..10] ; mbind $y = [1..10] ; mbind guard $x+$y == 10 ; say “$x+$y=10”; }
  352. 352. We're actually calling mbind on a list </li></ul>
  353. 353. List <ul><li>mdo { mbind $x = [1..10] ; mbind $y = [1..10] ; mbind guard $x+$y == 10 ; say “$x+$y=10”; }
  354. 354. We're actually calling mbind on a list
  355. 355. autobox </li></ul>
  356. 356. Continuations call_cc (&somefunc, ... ... ... )
  357. 357. Continuations somefunc
  358. 358. (clonable!) Continuations Somefunc for 1..3 {...}
  359. 359. Next steps? <ul><li>Devel::Declare + PPI </li><ul><li>(parse till end of statement) </li></ul></ul>
  360. 360. Next steps? <ul><li>Devel::Declare + PPI </li><ul><li>(parse till end of statement)
  361. 361. $x ← foo(); # monadic
  362. 362. bar(); # also monadic!
  363. 363. my $x = 12; # “normal” value
  364. 364. (e.g. no more 'mbind' keyword) </li></ul></ul>
  365. 365. Perl++ <ul><li>Not really a functional language...
  366. 366. But you can take it surprisingly far
  367. 367. (CPAN++) </li></ul>
  368. 368. What else can I do with monads? <ul><li>Parsing
  369. 369. Error handling
  370. 370. SQL generation </li></ul>
  371. 371. Wants monads now! <ul><li>Techniques are valuable now
  372. 372. Nicely wrapped implementation will be ready soon.... </li></ul>
  373. 373. Wants monads now! <ul><li>Techniques are valuable now
  374. 374. Nicely wrapped implementation will be ready soon....
  375. 375. Github: Acme::Monads – patches welcome </li></ul>
  376. 376. Thanks! <ul><li>questions? </li></ul>
  377. 377. Thanks! <ul><li>osfameron, </li><ul><li>#london.pm, #perl.it, #northwestengland.pm
  378. 378. CPAN
  379. 379. github </li></ul><li>Images </li><ul><li>Red pepper section, by docman http://www.flickr.com/photos/docman/107252072/ (cc-by-nc) </li></ul></ul>
  1. A particular slide catching your eye?

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

×