Blocks, Procs & Lambdas

9302bbf8e5f4e93a23f7d69bd50ebcd7?s=47 episko
September 19, 2012

Blocks, Procs & Lambdas

Demystifying what Blocks, Procs & Lambdas are in Ruby

9302bbf8e5f4e93a23f7d69bd50ebcd7?s=128

episko

September 19, 2012
Tweet

Transcript

  1. Blocks, Procs & Lambdas what you should know by Axel

    Vergult @episko http://www.github.com/episko
  2. Blocks Code in between do...end or {}

  3. [2, 23, 48, 101, 200].select do |n| n % 2

    == 0 end #=> [2, 48, 200] E.g.
  4. class Array def my_select inject([]) do |memo, n| memo <<

    n if yield(n) memo end end end [2, 23, 48, 101, 200].my_select do |n| n % 2 == 0 end #=> [2, 48, 200] Custom Array#select with yield
  5. We can’t save or manipulate blocks afterwards with this strategy

    unless ...
  6. ... we convert them to ...

  7. Procs Proc objects are blocks of code that have been

    bound to a set of local variables. Once bound, the code may be called in different contexts and still access those variables.
  8. def gen_times(factor) return Proc.new {|n| n*factor} end times3 = gen_times(3)

    times5 = gen_times(5) times3.call(12) #=> 36 times5.call(5) #=> 25 times3.call(times5.call(4)) #=> 60
  9. The “&” operator on an object 1) When object is

    a block => converts the block into a proc. 2) When object is a Proc => converts the object into a block 3) When object is not a Proc => calls #to_proc on the object to convert it into a block.
  10. class Array def my_select(&b) inject([]) do |memo, n| memo <<

    n if b.call(n) memo end end end [2, 23, 48, 101, 200].my_select do |n| n % 2 == 0 end #=> [2, 48, 200] Custom Array#select with a Proc 1) Convert block to a proc
  11. twice = Proc.new {|x| x * 2} [42, 84, 168].map(&twice)

    #=> [84, 168, 336] 2) Convert proc to a block
  12. [”42”, “84”, “168”].map(&:to_i) #=> [42, 84, 168] 3) Convert object

    to a block
  13. class Symbol def to_proc Proc.new {|x, *args| x.send(self, *args)} end

    end 3) How it typically works
  14. Lambdas Are Procs...

  15. lambda {}.class #=> Proc

  16. None
  17. 2 main differences

  18. Argument handling

  19. lambda {|a,b| [a,b]}.call(1,2,3) #=> ArgumentError lambda {|a,b| [a,b]}.call(1) #=> ArgumentError

    lambda {|a,b| [a,b]}.call([1,2]) #=> ArgumentError # Argument handling is rigid Lambda Proc Proc.new {|a,b| [a,b]}.call(1,2,3) #=> [1,2] # Ignores extra arguments Proc.new {|a,b| [a,b]}.call(1) #=> [1,nil] # Fills missing arguments with nil Proc.new {|a,b| [a,b]}.call([1,2]) #=> [1,2] # Expands a single array argument
  20. Lambdas Strict argument checking (like functions) Procs Loose argument checking

    (like blocks)
  21. Return context

  22. def return_in_lambda lambda { return ”Step 1” } return ”Step

    2” end puts return_in_lambda #=> Step 2 Lambda Proc def return_in_proc Proc.new { return ”Step 1” } return ”Step 2” end puts return_in_proc #=> Step 1
  23. Lambdas Return from its caller (like functions) Procs Return from

    the enclosing method (like blocks)
  24. Conclusion Procs are simply block objects Lambdas are block objects

    too but act like anonymous functions