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;
&:symis syntactic sugar for simple method calls