Ruby blocks, procs and lambdas
mouse 1777 · person cloud · link
Last update
2018-03-08
2018
03-08
« — »

Proc and lambda

Both types are anonymous functions and a lambda is just a special instance of Proc, their differences are:

  • Lambdas are defined with ->() {} or lambda() {} and procs with Proc.new {} or proc{}
  • Procs return from the current method (as they become part of the caller method), while lambdas return from the lambda itself (like calling a different method).
  • Procs do not care about the correct number of arguments, while lambdas will raise an exception.
1
2
3
4
5
6
7
8
l = -> { puts 'this is a lambda' }
l.class   # Proc
l.lambda? # true
l.call    # "this is a lambda"

l = ->(n) { n * 2 } # lambda with arguments
l.call 3    # 6
l.call 3, 4 # ArgumentError: wrong number of arguments

Pay attention at the different return behaviour:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
l = -> { return 1 }
p = Proc.new { return 1}

puts l.call
# 1

puts p.call # we cannot call return from the top-level context:
# LocalJumpError: unexpected return

def foo
  p = proc{ return 1}
  puts 'before'
  puts p.call # we can call return from a non top-level context
  puts 'after'
end

foo
# before
# 1


block

A block is an instance of Proc passed as a parameter to a method.

1
2
3
4
5
6
7
8
9
10
11
def implicit_block
  yield 1, 2, 3 if block_given? # execute block if passed
end

def explicit_block(&block)
  block.call 1, 2, 3 if block_given? # execute block if passed
  implicit_block &block # you can pass the block to another method
end

implicit_block{|p1, p2, p3| puts p1+p2+p3 } # prints 6
explicit_block{|p1, p2, p3| puts p1+p2+p3 } # prints 6 two times

Source: blackbytes, sitepoint closures