Introduction
In Ruby Magic, we enjoy delving into the magic that underlies the objects we use daily to comprehend how they function. We'll examine the distinctions between blocks, procs, and lambdas in this edition.
Functions can be stored in variables and passed as arguments to other functions in programming languages with first-class functions. Even other functions can be used by functions as return values.
A closure is an environment-based first-class function. The variables present when the closure was made up are mapped to by the environment. Even if these variables are defined in another scope, the closure will still have access to them.
While blocks, procs, and lambdas are used as closures in Ruby, first-class functions are not present. Code blocks can be passed to methods using blocks, and they can also be stored in variables using procs and lambdas.
Ruby Blocks
Code that can accept arguments and be executed later is captured in blocks.
Blocks are short pieces of code that can be created in Ruby and executed at a later time. Methods that yield blocks within the do and end keywords receive blocks as arguments
Curly braces or the do/end keyword pair can be used to separate blocks in Ruby. They may also function in an anonymous capacity.
A powerful programming technique is to encapsulate behavior in blocks and pass it to methods.
The #each method, which loops over enumerable objects, is just one of numerous examples.
1 [1,2,3].each do |n|
2 puts "#{n}!"
3 end
4
5 [1,2,3].each { |n| puts "#{n}!" }
A block is passed to the Array#each method in this example, which executes the block for each item in the array and prints the results to the console.
1 def each
2 i = 0
3 while i < size
4 yield at(i)
5 i += 1
6 end
In the while loop of this streamlined example of Array#each, yield is called to execute the passed block for each array element. Because the block is implicitly passed to the method, it should be noted that this method has no arguments.
Closures
First-class functions, free variables, and linguistic environment must all be understood to have a clear understanding of what closures are.
A method that can be used as an object and passed as a parameter to another function is a first-class function.
Free variables can still be accessed inside functions even though they are not declared in the function's parent scope.
The visibility of variables is referred to as lexical scoping. The ability to recognize a variable in a program by reading through the code is known as lexical scope, also referred to as eyeball scoping.
Use your interactive console to try this out:
parent_scope = "I'm available everywhere"
3.times do
inner_scope = "Only accessed in the scope above: -"
puts "#{inner_scope} #{parent_scope}}"
end
Lexical scoping is demonstrated in the code above. Only the block in which it is defined can see the inner scope. Ruby will throw an exception if you attempt to access it outside the block.
As a result, we can characterize closures as a section of code that stores variables in the environment in which it was created and can be used later. When determining a closure, we apply the following guidelines:
- It must serve a function.
- Some variables should be referred to in the function body.
- It is necessary to declare the variable in a parent scope.