Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

The Functional Rubyist: A Primer

149 views

Published on

Functional programming’s popularity is on the rise and support for FP is growing in Ruby. But can you really write functional code in Ruby? More importantly, why should you? Learn how Ruby enables functional programming concepts while maintaining highly readable and fun-to-write code.

Published in: Technology
  • Be the first to comment

  • Be the first to like this

The Functional Rubyist: A Primer

  1. 1. @jleo3 The Functional Rubyist A primer
  2. 2. @jleo3 joe leo (lucy’s daddy) twitter/github/linkedin: @jleo3
  3. 3. @jleo3 def method() TOGETHER WE WILL BUILD SOMETHING GREAT
  4. 4. @jleo3
  5. 5. @jleo3 DAVID A BLACK
  6. 6. @jleo3
  7. 7. @jleo3 (RUBYISTS / FRIENDS)
  8. 8. @jleo3
  9. 9. @jleo3 a note on purity Ruby Java 7 PHP Lisp
  10. 10. @jleo3 a purely functional language... ...guarantees referential transparency RUBY DOES NOT
  11. 11. @jleo3 A purely functional language... ...guarantees immutability RUBY DOES NOT
  12. 12. @jleo3 { haskell bullies }
  13. 13. @jleo3 side effects are necessary to do interesting things ● I/O ● raising exceptions ● outputting data to the terminal ● updating a record in a database ● anything else that changes state
  14. 14. @jleo3 what do most people mean when they fp? Remove side effects! Curry! Generics! Lazy Evaluation! Recurse! Tail-call optimize!
  15. 15. @jleo3 where to begin?
  16. 16. @jleo3 let ruby be your guide!
  17. 17. @jleo3 side-effect-free ruby ● String.upcase ● Enumerable.map ● Array.filter
  18. 18. @jleo3 bang! a side effect ● “my string”.upcase! ● [1, 2, 3, 4] << 5 ● { x: “ruby” }.fetch(:y)
  19. 19. @jleo3 an example Student#calculate_grade def calculate_grade(scores, student) case scores.sum / scores.size when 90..100 student.update_grade("A") when 80...90 student.update_grade("B") when 70...80 student.update_grade("C") when 60...70 student.update_grade("D") else student.update_grade("F") end end Student#calculate_grade def calculate_grade(scores) case scores.sum / scores.size when 90..100 "A" when 80...90 "B" when 70...80 "C" when 60...70 "D" else "F" end end
  20. 20. @jleo3 what is currying? breaking down… ● 1 function with many arguments… ● ...into many functions, each with 1 argument
  21. 21. @jleo3 what is currying? simple example: add add = -> (a, b) { a + b } #(1 function, 2 arguments) curried_add = -> (a) { -> (b){ a + b } } #(2 functions, each with 1 argument)
  22. 22. @jleo3 what is partial function application? ● Pass in a number of arguments less than the function’s arity ● Result: a new function with all of the passed-in arguments applied add = -> (a, b) { a + b } add = -> (5, b) { 5 + b } # partially applied; NOT VALID SYNTAX
  23. 23. @jleo3 but I’m lazy! i don’t want to have to think about all of that! ● You don’t have to! ● curry handles both currying and partial function application. ● add.curry
  24. 24. @jleo3 into action with curry and partial function application find_multiples = -> (x, arr) { arr.select { |el| el % x == 0 } }
  25. 25. @jleo3 Unique IRL; Generic in code ● Functions that return functions ● Building blocks for more specific functions ● Generics are to FP what Objects are to OOP
  26. 26. @jleo3 into action with curry and partial function application Generic: find_multiples_of = find_multiples.curry Individuated: find_multiples_of_3 = find_multiples_of.call(3) find_multiples_of_5 = find_multiples_of.call(5)
  27. 27. @jleo3 thinking in streams Find infinite multiples! find_first_multiples = -> (num, mult) { (1..).lazy.select { |x| x % mult == 0 }.first(num) }
  28. 28. @jleo3 recurse! Writing recursive functions is all about determining the “terminal clause.” Popular recursive functions: ● Factorial (terminal clause: x <= 1) ● Fibonacci (terminal clause: x <= 1) ● Sum Squares (terminal clause: x == 0)
  29. 29. @jleo3 VM, optimize thyself! RubyVM::InstructionSequence.compile_option = { tailcall_optimization: true, trace_instruction: false } demystifying tail-call optimization
  30. 30. @jleo3 demystifying tail-call optimization def factorial(x) return x if x == 2 x * factorial(x - 1) end def factorial(x, acc=1) return acc if x <= 1 factorial(x - 1, x * acc) end (RECURSIVE) (TAIL RECURSIVE)
  31. 31. @jleo3 Where can I learn more? You guessed it!
  32. 32. @jleo3 Where can I learn more? But also...
  33. 33. @jleo3 Thank you! Also, get @ me! - joe leo - twitter/github/linkedin: @jleo3 - defmethod.com Thank you to… - everyone at Rubyconf - Matz - Abby and the Program Committee - David A. Black

×