Last Updated: October 14, 2016
·
10.28K
· we4tech

Four types of ruby closures block, Proc, lambda and method

Ruby is an awesome piece of creation, Everyday I’m learning and discovering ruby in lot different and better way. just like other days today i dug more into how ruby closures work. here is my brief explanation after reading about ruby closures. thanks to the author for his wonderful writeup.

As we know ruby does lotta stuffs with closure, like in array iteration we are using closures in everywhere. Ruby has 4 type of closures – Block, Procs, Lambda and Method. I’m trying to explain them in brief. So i could use this post as my future reminder.

Block

It’s used with ‘&’ sign prefixed variable also executes using yield or *.call.

def say_hi_to(&block)
  puts "Say hi #{block.call}" 
end

say_hi_to { "hasan" }
#=> Say hi hasan

Procs (Procedures)

Its used as other ruby data types (array, hash, string, fixnum etc..), it’s reusable and could be used across multiple calls. also several procedures could be passed at a time.

def say_hi_to(block)
  puts "Say hi #{block.call}"
end

say_hi_to Proc.new { "hasan" }

#=> Say hi hasan

lambda

It’s a procedure (Proc) but with required parameter checking.

Also there is another difference between lambda and Proc. Proc’s “return” will stop method and will return from Proc on the other hand lambda‘s “return” will only return it’s own value to the caller method.

l = lambda { |a, b| ... }
l.call('A')
#=> Error need to pass 2 arguments

def whats_your_name?
  l = Proc.new { return "Karim" }
  l.call
  return "Rahim"
end

#=> "Karim"

Because Proc’s return is just like method’s own return. because it works like reusable code snippet.

Method

Method is another way around in ruby to use existing method as closure.

def hola
  puts 'hola'
end

def say_hola(block)
  block.call
end

say_hola method(:hola)

#=> hola

Thats the brief about Ruby closures. I learned it from hear - http://www.robertsosinski.com/2008/12/21/understanding-ruby-blocks-procs-and-lambdas/

3 Responses
Add your response

"Method is another way around in ruby to use existing method as closure."

Methods (at least the type you defined here) are not actually closures.

over 1 year ago ·

Hi @banister,

method(:some_method) returns Method class which acts like proc. could you please explain more so i could understand the gap :)

over 1 year ago ·

As far as I understand it, methods and Method objects are no closures.

By definition, a closure (unlike a normal function) has access to non-local variables even when invoked outside its immediate lexical scope.
In other words: A closure "remembers" all variables that were in scope when the function was created.
In the following example, `outside´ should be that non-local variable:

# Compare outputs, eg. in IRB:

outside = 7

# blocks are closures:
[1,2,3].map {|e| e+outside}
#=> [8,9,10]

# procs are closures:
proc {|e| e+outside}.call(4)
#=> 11

# lambdas are closures:
->(e) {e+outside}.call(5)
#=> 12

### but... ####################################################
# normal functions are NO closures
def fun(e)
  e + outside
end
fun(6)
#=> NameError: undefined local variable or method `outside' for main:Object

# methods are NO closures
method(:fun).call(7)
#=> NameError: undefined local variable or method `outside' for main:Object
over 1 year ago ·