Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Ruby ALL the Closures

Ruby ALL the Closures

I was asked to give an introductory talk about blocks, Procs and Lambdas in the local Ruby Meetup in Montevideo. This is the result.

6ed7c9c01ba124114f965ad3660bc276?s=128

Pablo Astigarraga

May 14, 2013
Tweet

Transcript

  1. Ruby ALL the closures Blocks, Procs and lambdas in ruby

    Tuesday, May 14, 13
  2. HOLA! • Pablo Astigarraga || PoTe • @poteland • github.com/pote

    Tuesday, May 14, 13
  3. Tuesday, May 14, 13

  4. Blocks, Procs and Lambdas Tuesday, May 14, 13

  5. Closures Tuesday, May 14, 13

  6. Tuesday, May 14, 13

  7. Closures Tuesday, May 14, 13

  8. Wikipedia A closure is a function or reference to a

    function together with a referencing environment - a table storing a reference to each of the non-local variables (also called free variables) of that function. A closure - unlike a plain function pointer - allows a function to access those non-local variables even when invoked outside of its immediate lexical scope. Tuesday, May 14, 13
  9. Closures def counter(): x = 0 def increment(y): nonlocal x

    x += y print(x) return increment Tuesday, May 14, 13
  10. Closures counter1_increment = counter() counter2_increment = counter() counter1_increment(1) # prints

    1 counter1_increment(7) # prints 8 counter2_increment(1) # prints 1 counter1_increment(1) # prints 9 Tuesday, May 14, 13
  11. Closures def pretty_method pretty_variable = 0 this_is_a_lambda = ->(argument) {

    pretty_variable += argument puts pretty_variable } this_is_a_lambda end Tuesday, May 14, 13
  12. Closures method_1 = pretty_method method_2 = pretty_method method_1.call(1) # =>

    1 method_1.call(7) # => 8 method_2.call(1) # => 1 method_1.call(1) # => 9 Tuesday, May 14, 13
  13. Blocks Tuesday, May 14, 13

  14. Blocks 5.times do puts 'Una más y no jodemos más!'

    end Tuesday, May 14, 13
  15. blocks 999.times do |index| puts "#{ index } elefantes se

    balanceaban sobre la tela de una araña, como veian que resistía fueron a buscar otro elefante" end Tuesday, May 14, 13
  16. Blocks ['python', 'ruby', 'lua'].each do |language| puts "#{ language }

    is a pretty cool language!" end #=> python is a pretty cool language! # ruby is a pretty cool language! # lua is a pretty cool language! Tuesday, May 14, 13
  17. Blocks 5.times do |index| puts 'Lalala' end 5.times { |index|

    puts 'Lalala' } 5.times { |index| puts 'Lalala' } Tuesday, May 14, 13
  18. Blocks Blocks are chunks of code that are used by

    a method. Tuesday, May 14, 13
  19. How? Tuesday, May 14, 13

  20. Let’s make our own Tuesday, May 14, 13

  21. <queue live coding> Tuesday, May 14, 13

  22. Procedures A.K.A “Procs” Tuesday, May 14, 13

  23. Procs p = Proc.new do |text| text.split(' ').each do |word|

    puts "#{ word } \n" } end puts "- ♪ 㽈" end p.call("uno dos tres cuatro cinco cinco seis") Tuesday, May 14, 13
  24. Procs p = Proc.new do |text| text.split(' ').each do |word|

    puts "#{ word } \n" } end puts "- ♪ 㽈" end p.call("uno dos tres cuatro cinco cinco seis") Tuesday, May 14, 13
  25. p = Proc.new do | text| text.split(' ').each do |word|

    puts "#{ word } \n" } end Tuesday, May 14, 13
  26. p = Proc.new do |text| text.split(' Tuesday, May 14, 13

  27. Procs are objects Tuesday, May 14, 13

  28. <queue live coding> Tuesday, May 14, 13

  29. blocks == Procs Tuesday, May 14, 13

  30. Who has done this? (function () { $.ajax({ url: "json.txt",

    dataType: 'json', cache: false, success: function (data, textStatus, jqXHR) { if (data.mySuccessProperty == "succeeded") { doX(); (function () { eval(data.dynamicFunction)(); })(); } else { doY(); (function () { alert("Z"); })(); } }, error: function (jqXHR, textStatus, error) { // handle error alert("error" + error); } }); })(); Tuesday, May 14, 13
  31. Who has done this? (function () { $.ajax({ url: "json.txt",

    dataType: 'json', cache: false, success: function (data, textStatus, jqXHR) { if (data.mySuccessProperty == "succeeded") { doX(); (function () { eval(data.dynamicFunction)(); })(); } else { doY(); (function () { alert("Z"); })(); } }, error: function (jqXHR, textStatus, error) { // handle error alert("error" + error); } }); })(); Tuesday, May 14, 13
  32. Procs callbacks = { success: Proc.new { |result| Services::EverythingWentWell.call(result: result)

    Services::NotifyEveryone.call }, error: Proc.new { |result| # Clean up mess # Log problem # Dance Polka } } def method_that_does_things(callbacks) if do_things callbacks[:success].call(result_of_things) else callbacks[:error].call(result_of_things) end end Tuesday, May 14, 13
  33. Procs def persist!(hooks) hooks[:before_validate].call hooks[:before_save].call save hooks[:after_save].call end Tuesday, May

    14, 13
  34. Lambdas Tuesday, May 14, 13

  35. Lambdas class Array def iterate!(code) self.each_with_index do |n, i| self[i]

    = code.call(n) end end end array = [1, 2, 3, 4] array.iterate!(lambda { |n| n ** 2 }) puts array.inspect # => [1, 4, 9, 16] Tuesday, May 14, 13
  36. Lambdas def args(code) one, two = 1, 2 code.call(one, two)

    end args(Proc.new{|a, b, c| puts "Give me a #{a} and a #{b} and a #{c.class}"}) args(lambda{|a, b, c| puts "Give me a #{a} and a #{b} and a #{c.class}"}) # => Give me a 1 and a 2 and a NilClass # *.rb:8: ArgumentError: wrong number of arguments (2 for 3) (ArgumentError) Tuesday, May 14, 13
  37. Lambdas def proc_return Proc.new { return "Proc.new"}.call return "proc_return method

    finished" end def lambda_return lambda { return "lambda" }.call return "lambda_return method finished" end puts proc_return puts lambda_return # => Proc.new # => lambda_return method finished Tuesday, May 14, 13
  38. Questions? Tuesday, May 14, 13

  39. Gracias! @poteland Tuesday, May 14, 13

  40. Links @poteland * Understanding Ruby Blocks, Procs and Lambdas -

    http://bit.ly/9qcstJ * This Talk - http://bit.ly/18IFJmP * More info - http://bit.ly/r8BnTA Tuesday, May 14, 13