Closures in Ruby

In Ruby, closure is a function or a block of code with variables that are bound to the environment that the closure is called. Or in other words, closure can be treated like a variable that can be assigned to another variable or can be pass to any function as an argument.

  • A closure block can be defined in one scope and can be called in a different scope.
  • Closure always remember the variable within its scope at the creation time and when its called it can access the variable even if they are not in the current scope i.e closure retain its knowledge of it lexical environment at the time of defining.
  • In Ruby, Blocks, procs, lambdas are clousers.

Blocks

Blocks are the simplest form of Ruby closure. It is not an object but it is a piece of code which is enclosed in between braces {} or do…end.

  • You can pass one or more variables into your block depending upon how the code block is written.
  • You can use yield statement to call a block within a method with a value.
  • It does not have their own name.

Syntax:

Using {}

 block_name { #statements_to_be_executed }

Using do…end



 block_name do 

   #statement-1  
   #statement-2  
   .
   .
end 

Example 1:

filter_none

edit
close

play_arrow

link
brightness_4
code

# Ruby program to illustrate blocks
arr = [10, 11, 13, 41, 59]
  
arr.each do | item |
puts item
end

chevron_right


Output:

10
11
13
41
59

Example 2:

filter_none

edit
close

play_arrow

link
brightness_4
code

# Ruby program to illustrate blocks
  
# Method with single yield statement
def print_once
      
    # statement of method
    puts"Hello! I am Method"
      
  # using yield statement
  yield
end
  
# Block 1
print_once { puts "Hello! I am Block 1" }
  
# Method with two yield statement 
def print_twice
      
  # using yield statement
  yield
  yield
end
  
# Block 2
print_twice { puts "Hello! I am Block 2" }

chevron_right


Output:

Hello! I am Method
Hello! I am Block 1
Hello! I am Block 2
Hello! I am Block 2

Explanation: In the above example, method name is print_once. First, the method statement is called which will display “Hello! I am Method. But as soon as yield statements execute the control goes to block and block will execute its statements and print “Hello! I am Method”. As soon as the block will execute it gives control back to the method and the method will continue to execute from where yield statement called. You can also use multiple yield statements in the single method as shown in the print_twice method.

Procs

Now the second type of ruby closure is Procs that is very much similar to block but with a few differences like a procs is assigned or store in a variable and it is executed by calling .call method. You can pass one or more proc to a method. As we know that block is not an object but Proc is an object. It is a block that turned into an object of the Proc class, that why the Proc looks similar to the instantiation of a class.
Syntax:

variableName = Proc.new {# Statement}

# Executing Procs
variableName.call

Example 1:

filter_none

edit
close

play_arrow

link
brightness_4
code

# Ruby program to illustrate Procs
  
# Creating proc
example = Proc.new{"GeeksforGeeks"}
  
# Executing proc
# Using .call method
puts example.call

chevron_right


Output:



GeeksforGeeks

Explanation: In the above example, we are assigning a block to an instance of the Proc class and assigning it to the variable, i.e., example and calling the method .call on it.
Example 2:

filter_none

edit
close

play_arrow

link
brightness_4
code

# Ruby program to illustrate Procs
  
# Creating proc
a = Proc.new {|x, y| "x = #{x}, y = #{y}" }
  
# Executing proc
puts a.call(1, 2)      
puts a.call([2, 1])    
puts a.call(3, 4, 8)   
puts a.call(9)   

chevron_right


Output:

x = 1, y = 2
x = 2, y = 1
x = 3, y = 4
x = 9, y = 

Explanation: In this example, we pass the argument in Proc using .call method. Procs accept arguments more generously. It filled missing arguments with nil and a single array arguments are deconstructed if the proc has multiple arguments. It does not give an error on extra arguments.

Lambda

We can say that lambda and Procs are kind of same there isn’t much difference. Also, we can say that a lambda is a way to define a block & its parameters with some special syntax. Lambda is like a regular method because they impose the number of parameters passed when they’re called and also they return like normal methods(It treat return keyword just like methods). If you pass a parameter to a lambda that doesn’t expect it, then you will get an ArgumentError.
Syntax:

variableName = -> {# Statement}

Example 1:

filter_none

edit
close

play_arrow

link
brightness_4
code

# Ruby program to illustrate lambda
  
# Creating lambda
times_one = ->(x){ x * 2 }
  
# Displaying result
puts times_one.call(10)
  
# Creating lambda
times_two = lambda{"GeeksforGeeks"}
  
# Displaying result
puts times_two.call

chevron_right


Output:

20
GeeksforGeeks

Example 2:

filter_none

edit
close

play_arrow

link
brightness_4
code

# Ruby program to illustrate lambda
  
# Creating lambda
my_lambda = -> {puts "Hey"}
  
# Creating lambda with argument
my_lambda_args = -> (x) {puts "Hello! " + x }
  
# Calling lambda
my_lambda.call
  
my_lambda_args.call("GeeksforGeeks")

chevron_right


Output:

Hey
Hello! GeeksforGeeks



My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.


Article Tags :

Be the First to upvote.


Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.