Open In App

Closures in Ruby

Last Updated : 03 Jul, 2020
Improve
Improve
Like Article
Like
Save
Share
Report

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:




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


Output:

10
11
13
41
59

Example 2:




# 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" }


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:




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


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:




# 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)   


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:




# 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


Output:

20
GeeksforGeeks

Example 2:




# 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")


Output:

Hey
Hello! GeeksforGeeks


Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads