$30 off During Our Annual Pro Sale. View Details »

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.

Pablo Astigarraga

May 14, 2013
Tweet

More Decks by Pablo Astigarraga

Other Decks in Programming

Transcript

  1. Ruby ALL the
    closures
    Blocks, Procs and lambdas in ruby
    Tuesday, May 14, 13

    View Slide

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

    View Slide

  3. Tuesday, May 14, 13

    View Slide

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

    View Slide

  5. Closures
    Tuesday, May 14, 13

    View Slide

  6. Tuesday, May 14, 13

    View Slide

  7. Closures
    Tuesday, May 14, 13

    View Slide

  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

    View Slide

  9. Closures
    def counter():
    x = 0
    def increment(y):
    nonlocal x
    x += y
    print(x)
    return increment
    Tuesday, May 14, 13

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  13. Blocks
    Tuesday, May 14, 13

    View Slide

  14. Blocks
    5.times do
    puts 'Una más y no jodemos más!'
    end
    Tuesday, May 14, 13

    View Slide

  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

    View Slide

  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

    View Slide

  17. Blocks
    5.times do |index|
    puts 'Lalala'
    end
    5.times { |index|
    puts 'Lalala'
    }
    5.times { |index| puts 'Lalala' }
    Tuesday, May 14, 13

    View Slide

  18. Blocks
    Blocks are chunks of code that are used
    by a method.
    Tuesday, May 14, 13

    View Slide

  19. How?
    Tuesday, May 14, 13

    View Slide

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

    View Slide


  21. Tuesday, May 14, 13

    View Slide

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

    View Slide

  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

    View Slide

  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

    View Slide

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

    View Slide

  26. p = Proc.new
    do |text|
    text.split('
    Tuesday, May 14, 13

    View Slide

  27. Procs
    are
    objects
    Tuesday, May 14, 13

    View Slide


  28. Tuesday, May 14, 13

    View Slide

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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  33. Procs
    def persist!(hooks)
    hooks[:before_validate].call
    hooks[:before_save].call
    save
    hooks[:after_save].call
    end
    Tuesday, May 14, 13

    View Slide

  34. Lambdas
    Tuesday, May 14, 13

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  38. Questions?
    Tuesday, May 14, 13

    View Slide

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

    View Slide

  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

    View Slide