GGistDev

Proc and Lambda in Ruby

Callable objects with subtle differences in arity and return behavior.

Basics

Create with proc/Proc.new or lambda/->; call with call.

p1 = proc { |x| x.to_i }
l1 = ->(x) { x * 2 }

p1.call("7")  # => 7
l1.call(3)     # => 6

Arity and return

Lambdas enforce arity and return returns from the lambda; procs are lenient and return exits the enclosing method.

def demo
  p = proc { |x| return :from_proc }   # returns from demo
  p.call(1)
  :after
end

demo # => :from_proc

l = ->(x) { return x * 2 }  # returns from lambda only
l.call(3)  # => 6

Conversions with &

Convert a block to a Proc with █ pass a Proc as a block with &.

def with_block(&blk)
  blk.call(10)
end

adder = ->(n) { n + 5 }
with_block(&adder)  # => 15

Closures and capturing

Procs/lambdas capture surrounding variables by reference.

def counter
  n = 0
  -> { n += 1 }
end

c = counter
c.call  # 1
c.call  # 2

Currying and partial application

Lambdas can be curried; use curry to build partially applied functions.

add = ->(a,b) { a + b }
add5 = add.curry[5]
add5[3]  # => 8

Symbol-to-proc nuances

&:method is shorthand for { |x| x.method }; it uses to_proc under the hood.

["a","b"].map(&:upcase)  # => ["A","B"]

Summary

  • Use lambdas for predictable arity and returns; procs are looser
  • & converts between blocks and Procs; closures capture locals
  • Curry lambdas for reusable partials; &:sym is syntactic sugar for simple method calls