Category Archives: Uncategorized

Closures in Ruby – Part2

Blocks, Procs,  Lambdas and Methods come under the category of closures in Ruby. The concept of Closures is explained in detail at Part1 of this blog. In this we blog we are going to discuss in detail about Blocks, Procs, Lambdas and Methods.

Blocks & Procs

Blocks are chunks of code that can be passed to a method. This can be achieved in many ways. Try following the below sample codes to learn more.

class Maths

def initialize(val)

@val = yield(val)

p @val

end

def print

yield(@val)

end

end

num = Maths.new(10){|val| val = val * 10}

num.print{ |val| val = val * 20

p val}

Output:

100

2000

In all the method definitions inside the class ‘Maths’, the key word ‘yield’ means that it would accept any block of  code passed to it. When the object ‘num’ is created from the class Maths the ‘initialize’ method is invoked which accepts a parameter named ‘val’. This variable ‘val’ is then yielded to the block of code passed during the creation of the object “{|val| val = val * 10}”. The ‘val = 10’ is thus multiplied by 10 and the result ‘100’ in then stored in @val.

The print method once again yields this ‘@val’ to another block of code passed during the ‘print’ method call and gets multiplied by 20 and the result 2000 is printed as the result. Thus we can understand how blocks can be manipulated to perform different actions depending upon the requirement.

Now let us imaging that we want to perform the same actions on 5 more objects say num1, num2, num3, num4, num5. We should explicitly pass the blocks of code for each object as below:

num1 = Maths.new(10){|val| val = val * 10}

num1.print{ |val| val = val * 20

p val}

num2 = Maths.new(10){|val| val = val * 10}

num2.print{ |val| val = val * 20

p val}

etc..

Does this not make the code redundant?  The cost of coding will also be high. It would be great if we can store this block of code in a variable and pass the variable to each object to achieve the same results, right? This is where Procs come into picture. Look at the below code:

class Maths

def initialize(val,code)

@val = code.call(val)

end

def print(code)

code.call(@val)

end

end

mul = Proc.new {

|val| val = val * 10

p val

}

mul1 = Proc.new {

|val| val = val * 20

p val

}

num = Maths.new(10,mul)

num.print(mul1)

Output:

100

2000

The variable ‘mul’ and ‘mul1’ stores the block of code and is passed to the methods. This achieves the same result as the block. Also, if we want to perform the same operation of multiple objects we just have to use the proc appropriately. Example ‘num1 = Maths.new(20,mul) , num2 = Maths.new(29,mul)’ etc.

Interestingly, blocks are Proc objects! Look at the code below:

def methodnew(&block)

block.class

end

p methodnew{p “I am a block”}

Output:

Proc

Having learnt about blocks, it would be much easier to understand what Proc is and when should we use them. Procs are useful if we wish to execute a block of code multiple times.

Lambdas:

Let us look at the below example code to understand Lambdas:

class Maths

def initialize(val,code)

@val = code.call(val)

end

def print(code)

code.call(@val)

end

end

mul = lambda {

|val| val = val * 10

p val }

mul1 = lambda {

|val| val = val * 20

p val}

num = Maths.new(10,mul)

num.print(mul1)

Output:

100

2000

Lambdas are similar to Procs but the difference is, lambdas checks the number of arguements that is passed to it but a Proc does not check the number of arguements passed to it. For example

class Maths

def initialize(val,code)

@val = code.call(val)

end

end

mul = Proc.new {

|val,val1| val = val * 10

p val

p val1

}

mul1 = lambda {

|val, val1| val = val * 10

p val

p val1

}

num = Maths.new(10,mul)

num = Maths.new(10,mul1)

Output:

The output after calling the Proc:

100

nil

The output after calling Lambda:

example3.rb:29:in `block in <main>’: wrong number of arguments (1 for 2) (ArgumentError)

from example3.rb:11:in `call’

from example3.rb:11:in `initialize’

from example3.rb:35:in `new’

from example3.rb:35:in `<main>’

There is also one more difference between Procs and Lambdas.  Let us look at the below code:

class Maths

def initialize(val)

@val =val

end

def print(code)

code.call(@val)

return “return from method”

end

end

mul = Proc.new {

|val| val = val * 10

p val

return “return from Proc”

}

mul1 = lambda {

|val| val = val * 10

p val

return “return from Lambda”

}

num = Maths.new(10)

p num.print(mul1)

Output :

100

“return from method”

We see that Lambda continues code execution even after encountering return inside lambda.  Whereas Proc does not permit return commands when passed to a method and gives error as below:

p num.print(mul)

Output:

100

example3.rb:30:in `block in <main>’: unexpected return (LocalJumpError)

from example3.rb:17:in `call’

from example3.rb:17:in `print’

from example3.rb:45:in `<main>’

If you call a Proc directly inside a method without passing it as a parameter like the code below:

def method1

Proc.new{return “proc”}.call

return “from method1”

end

def method2

lambda{return “lambda”}.call

return “from method2”

end

p method1  #Output : proc

p method2 # Output: from method2

Lambda thus continues its execution even after encountering a return whereas Proc stop its execution after encountering first return.  When we expect out code to strictly check the number of arguments and continue program execution till the end we should use Lambdas else we should use Procs.

Methods:

‘Methods’ are another way of passing a block of code to a method and is similar to Lambdas. For example:

class Maths

def initialize(val,code)

@val = code.call(val)

end

def print(code)

code.call(@val)

end

end

def mul(val)

val = val * 10

p val

end

def mul1(val)

val = val * 20

p val

end

num = Maths.new(10,method(:mul))

num.print(method(:mul1))

Output:

100

2000

Thus we come to the conclusion of Closures in Ruby. I hope this blog was useful to you.

References:

1. Closure (computer science). (n.d.). , from http://www.princeton.edu/~achaney/tmve/wiki100k/docs/Closure_(computer_science).html

2. Alan Skorkin : “http://www.skorks.com/2010/05/closures-a-simple-explanation-using-ruby/

3. Robert Sonsinski: “http://www.robertsosinski.com/2008/12/21/understanding-ruby-blocks-procs-and-lambdas/

Advertisements

Leave a comment

Filed under Uncategorized

Closures in Ruby – Part1

Hello readers! welcome to my blog spot once again!

We all have come across Procs, Blocks, Lambdas and Methods in Ruby and have found them to be quite useful! but what are the differences between them? when to use each of them? In order to answer these questions we should first understand the concept of “Closures”. There are 2 parts in this blog: The first part explains about closures and the second part explains about Procs, Blocks and Lambdas in detail!

What are Closures ?

“In computer science, a closure is a first-class function with free variables that are bound in the lexical environment.”[1]

Let’s try to understand the terms used in the above definition! Firstly a closure is a first-class function. A first-class function is a function or a method that can be treated like an object and can be passed as a parameter to another method/function.

Secondly, because of their ability to be passed around like a parameter, closures retain the values of its local variables at the time of their creation and can access the values of the variables even when the closures are called out of the scope of the variables.

The following ruby code would be helpful to understand closures better:

# Add 2 strings

class Maths

def initialize(v1)

@v1 = v1

end

def sum(v2)

lambda { puts ” #{@v1}” + ” #{v2}”}

end

end

def call_closure(closure)

closure.call

end

num = Maths.new(“hi”)

var = num.sum(“hello”)

call_closure(var)

Output:

hi hello

In the above code, the method sum creates a closure using Lambdas. The parameter passed to this closure is ‘v2’ which is a local variable to the method ‘sum’. Now when the method sum is assigned to a variable ‘var’ as in the code “var = num.sum(“hello”) “, the method ‘sum’ returns the lambda and stores it into the variable var. Now this variable var is passed as a parameter to the method call_closure. This satisfies the first property of closures (first-class functions), the ability of a method to be passed like a parameter to another method. Inside the method call_closure the lambda is invoked and the value ‘v1’ and ‘v2’ is accessed even though they are out of scope in the method call_closure but within the lambda they are still alive. This satisfies the second property of retaining the values of the variables even though they are out of scope when the closure is called. In other words closures retain the knowledge of the variables in their lexical environment.

Not all programming languages support closures. In ruby closures are supported via Procs, Blocks and Lambdas. Programming languages implement closures in 2 ways:

  1. Closures create a copy of the variables when they are defined and are used where ever they are invoked.
  2. Closures keep a reference to the variables and access them where ever the closure is invoked.

Ruby uses the second method to retain the knowledge of its lexical environment. This would also mean that the values of these variables are susceptible to change inside the closure where ever it is passed. This can be both advantageous and disadvantageous. The advantage being: writing less code and following the DRY principle. The disadvantage being: These variables are not protected and can’t hold sensitive data and these variables are not eligible for garbage collection. Using too many of these variables might affect performance! Nevertheless closures are very handy and dynamic and can be very useful. The below ruby code would help us assess its pluses and minuses.

class Maths

def initialize(v1)

@v1 = v1

end

def square(closure)

p “The square of the number is: #{closure.call(@v1)}”

end

def change_square

lambda {

@v1 = @v1 + 1

p “The square of the changed number is: #{@v1**2}”

}

end

end

num = Maths.new(5)

num.square(lambda{|n| n**2} )

num.change_square.call

Output:

“The square of the number is: 25”

“The square of the changed number is: 36”

In the above code a closure is passed to the method ‘square’ to find the square of a number. The code can also be changed during the run time to perform other functions like finding the cube of the number or multiple of a number and so on. Thus closures are handy to execute any block of code, making the code highly flexible.

In Ruby closures keep a reference to the variables defined inside it as a result they are liable for change by other closures. For example in the above code, the method ‘change_square’ increments the value of @v1 and squares the result. The variable @v1 thus changes based on the code used inside the closure. Thus closures should be used with care. Now let’s look at the below code:

class Maths

def initialize(v1)

@v1 = v1

end

def multiple

lambda{

@v1 = @v1*2

p “The second multiple of the number is: #{@v1}”

}

end

end

num = Maths.new(5)

num.multiple.call

num.multiple.call

num.multiple.call

num.multiple.call

p “————–”

num1 = Maths.new(5)

num1.multiple.call

num1.multiple.call

Output:

“The second multiple of the number is: 10”

“The second multiple of the number is: 20”

“The second multiple of the number is: 40”

“The second multiple of the number is: 80”

“————–”

“The second multiple of the number is: 10”

“The second multiple of the number is: 20”

See how the same variable @v1 has been modified by closures called by 2 objects of the same class! Thus closures must be used with caution to avoid confusion and to protect data.

Hope you found this blog useful! Please feel free to share your comments. In the part-2 of this blog we will have a look at the four types of closures used in Ruby: The Procs, Blocks, Lambdas and methods. I thank Alan Skorkin and Robert Sosinski for inspiring me to write this blog

References:

1. Closure (computer science). (n.d.). , from http://www.princeton.edu/~achaney/tmve/wiki100k/docs/Closure_(computer_science).html

2. Alan Skorkin : “http://www.skorks.com/2010/05/closures-a-simple-explanation-using-ruby/

3. Robert Sonsinski: “http://www.robertsosinski.com/2008/12/21/understanding-ruby-blocks-procs-and-lambdas/

Leave a comment

Filed under Uncategorized