In Ruby Magic, we enjoy diving into the magic that underlies the objects we use daily to comprehend how they function. We'll examine blocks, procs, and lambdas in this blog.
Blocks, Procs, and Lambdas are the three primary functions used by Ruby. Code blocks can be passed to methods using blocks, and they can also be stored in variables using procs and lambdas.
Blocks
Little anonymous functions called "ruby blocks" can be provided in methods. They may have several parameters and are enclosed in a do/end statement (often when the block has many lines) or between brackets {} (if the block is a one-liner).
Example:
['x','y','z'].each do |n|
puts "#{n}!"
end
['a','b','c'].each { |n| puts "#{n}!" } # the one-line equivalent.
You can also try this code with Online Ruby Compiler
A block is supplied to the Array#each method in this example, which executes the block for each item in the array and outputs the results to the console.
Output:
x
y
z
a
b
c
In Ruby, blocks are essential in the following ways:
The block has a return value and can take arguments.
Block doesn't have a name of its own.
Code fragments comprise a block.
A block can be given to a method call or is always called together with a function.
The yield statement invokes a block within a method with a value.
From within the method to which they are provided, blocks can be called methods.
Procs
What if you want to pass your function two blocks? How may your block be saved as a variable?
Ruby added procs so that blocks could be passed. Code snippets, known as "proc objects," are tied to a group of local variables. Once bound, the code can continue to access those variables when invoked in other contexts.
Creating Procs
Associating a block with a method specified with an ampersand-prefixed block argument will create a Proc object. Nothing prevents a procedure of this kind from returning the Proc object for use elsewhere:
# This method creates a proc from a block
def makeproc(&p) # Convert associated block to a Proc and store in p
p # Return the Proc object
end
You can also try this code with Online Ruby Compiler
Adder is now a reference to a Proc object. When a proc object is made this way, it is a proc, not a lambda. Every Proc object has a call method that, when used, executes the program code found in the block from which it was generated. For instance:
Proc objects can be provided to methods, saved in data structures, and used in other ways like any other object, in addition to invoking.
Proc.new
The most obvious way to create a new instance of the Proc class is to use this standard new method, which is supported by most classes. Proc.new returns a Proc object that is a proc and requires no arguments (not a lambda). A proc representing the block is returned when Proc.new is called with an attached block.
A proc representing the block associated with the containing method is returned if Proc.new is called without a block from within a method that does have an associated block. An option for using an ampersand-prefixed block argument in a method specification is to use Proc.new in this manner. For instance, the following two approaches are equivalent:
def invoke(&b)
b.call
end
def invoke
Proc.new.call
end
The Arity of a Proc
The quantity of arguments that a proc or lambda expects is known as its arity. (The word is derived from unary, binary, ternary, etc. "are." 's the suffix.) The arity method of proc objects returns the number of arguments they anticipate. For instance:
lambda{||}.arity # => 0. There won't be any arguments
lambda{|x| x}.arity # => 1. Expected only one argument
lambda{|x,y| x+y}.arity # => 2. Two arguments expected
You can also try this code with Online Ruby Compiler
The == method only returns true if one Proc is a clone or duplicate of the other:
p = lambda {|y| y*y }
q = p.dup
puts p == q # => false: the two procs are equal
puts p.object_id == q.object_id # => false: they are not the same object
You can also try this code with Online Ruby Compiler
main.rb:2:in `block in <main>': wrong number of arguments (given 3, expected 1) (ArgumentError)
from main.rb:3:in `<main>'
In this, they behave much more like methods and may result in fewer perplexing errors.
Behavior with Return
Instead of attempting to return from the method's outside context, lambda functions will treat the return as a local return, this shows the difference between procs and lambdas:
def some_method(a, b)
adds_three_unless_gt_three = -> v {
return v if v > 3
v + 3
}
puts adds_three_unless_gt_three.call(a) +
adds_three_unless_gt_three.call(b)
end
some_method(1,1) #=>8
some_method(5,5) #=>10
You can also try this code with Online Ruby Compiler
For defining lambdas as literals, Ruby 1.9 enables a completely new syntax. We'll start with a Ruby 1.8 lambda that was developed using the lambda method:
suc = lambda {|y| y+1}
You can also try this code with Online Ruby Compiler
Procs and lambdas cannot be invoked in the same manner that methods may since they are objects and not methods. You cannot call p as a method if it refers to a Proc object. However, since p is an object, you can call one of p's methods. The Proc class defines a method called call. The code in the original block is executed when this method is used. The arguments you send to the call method become the arguments for the block, and the block's return value becomes the call method's return value:
f = Proc.new {|x,y| 1.0/(1.0/x + 1.0/y) }
z = f.call(2,4)
You can also try this code with Online Ruby Compiler
The Proc class also defines the array access operator to function similarly to the call. This indicates that you can call a proc or lambda using a syntax similar to a method invocation, except that square brackets are used in place of parentheses. For instance, the code below might be used in place of the proc invocation above:
z = f[x,y]
You can also try this code with Online Ruby Compiler
.() appears to be a method call without the method name. This is syntactic sugar that calls the call method rather than an operator that can be defined. It is not restricted to Proc objects and can be used with any object that defines a call method.
Summary of Procs and Lambdas
We've now thoroughly explored blocks, procs and lambdas; let's zoom out and summarize the comparison.
In Ruby, blocks are frequently used to pass pieces of code to functions. A block can be implicitly passed without being converted into a proc using the yield keyword.
When sending a block to a method with ampersand-prefixed parameters, the method's context creates a proc. Procedures operate like blocks despite being able to be stored in a variable.
By enforcing arity and returning as methods rather than in their parent scope, lambdas are procs that behave like methods. Check out this problem - Find Duplicate In Array
Frequently Asked Questions
What are procs in Ruby?
A Proc object is a container for a block of code that can be called, handed to another Proc or method, and saved in a local variable. The foundation of Ruby's functional programming features is the concept of Proc.
What are lambdas in Ruby?
In Ruby, a lambda is an object similar to a proc. Unlike a proc, a lambda requires a specific number of arguments passed to it, returning to its calling method rather than returning immediately.
What distinguishes procs and lambdas in particular?
The primary variations. A lambda, as opposed to a proc, first verifies the number of arguments supplied to it.
Why do we use blocks in Ruby?
You have utilized blocks if you have previously used each. Because it enables you to store and reuse a small portion of logic (code), Ruby blocks are helpful. This might entail sending information to a file, determining whether two elements are equal, or even producing an error message.
What are the critical features of the lambda function?
Syntactically, lambda functions can only return a single expression. They can be utilized inside of other functions as an anonymous function. Because lambda functions always return a single expression, they do not require a return statement.
Conclusion
In this post, you learned how to create and work with blocks, procs and lambdas in ruby through various examples.
Here are a few key websites that will aid in your exploration of Ruby's Procs and Lambdas.