Page Content

Tutorials

Blocks In Ruby: Anonymous Methods For Contextual Code

Blocks in Ruby

In Ruby, a block is a way to group statements together and pass them as arguments to methods. They are essentially anonymous functions that are associated with a method invocation. Blocks provide a flexible mechanism to define behavior that can be executed within a specific context.  A fundamental and very unique aspect of Ruby is its blocks, which are sections of code that can be supplied to or coupled with method calls. An anonymous method is essentially what a Ruby code block is. It includes the necessary context for the Ruby code to run.

Syntax and Delimiters

Blocks are only considered legitimate when they immediately follow a method call; otherwise, they are not self-contained.

For defining blocks, Ruby offers two main syntaxes:

Curly Braces ({...}): It is normally advised to use this format for brief, one-line chunks.

do...end Keywords: When the block spans several lines, this format is usually utilized to improve readability.

Note on Precedence: The do…end keywords have a lower precedence than the curly brace syntax ({}), which binds more firmly. When curly braces are used in a method call without parenthesis, the block may inadvertently be bound to the final parameter rather than the method.

At the beginning of a block, there are vertical bars (|…|) that define the parameters that the block can accept.

Code Examples (Syntax)

Single-line block using curly braces:

# The `times` method is an iterator defined on integers.
3.times { print "Ruby! " } 
# Prints "Ruby! Ruby! Ruby! " 

# Iterating over an array 
[39-41].each { |i| puts i * i }

Output

Ruby! Ruby! Ruby! 4

Multi-line block using do...end:

# The `upto` method is an iterator defined on integers.
1.upto(3) do |i|
  if i % 2 == 0
    puts "#{i} is even."
  else
    puts "#{i} is odd."
  end 
end
# 1 is odd.
# 2 is even.
# 3 is odd.

Output

1 is odd.
2 is even.
3 is odd.

Blocks and Iterators (Yield)

Similar to loops, Ruby’s sophisticated iterator methods (such as each, times, and map) are built on blocks.

A method uses the yield keyword to run an attached block. The yield statement gives the block temporary control back from the iterator method. after the yield statement is called, control moves to the block, and after the block is finished, the original method’s execution instantly resumes.

Values passed to the block from the yield statement are received via the block parameters specified in pipes (|…|).

When calling yield, you can use the block_given? method to see if a block was sent to a method. The outcome of calling yield without a block in between is a LocalJumpError.

Examples of Code (Yield and Custom Methods)

Defining a method that uses yield:

def call_block
  puts "Start of method"
  yield # Passes control to the block
  yield # Passes control again
  puts "End of method"
end

call_block { puts "In the block" }
# produces:
# Start of method
# In the block
# In the block
# End of method

Output

Start of method
In the block
In the block
End of method

Passing arguments via yield to a block:

def animals
  yield "Tiger" 
  yield "Giraffe"
end

animals { |x| puts "Hello, #{x}" }
# Hello, Tiger
# Hello, Giraffe

Output

Hello, Tiger
Hello, Giraffe

Blocks as Closures and Proc Objects

Blocks and the idea of closures are closely related. Because it retains the variable bindings (context) that were in place when it was defined, a block is a closure. As a result, even if the block is performed later, when the local variables are technically out of scope, it can still access and use them.

Despite being syntactic structures, blocks “die once executed” since they are not objects in and of themselves and cannot be altered or stored for subsequent use.

The conversion of a block into a lambda or a Proc object is necessary in order to treat it as a first-class object. Kernel#lambda or Proc.new can be used explicitly, or the last parameter of a method definition can be prefixed with an ampersand (&) to accomplish this conversion implicitly.

Control Flow within Blocks

Usually, the result of the last expression evaluated inside a block is its return value. Within blocks, control flow keywords exhibit distinct behaviour:

next: Causes the block to stop running in the current iteration and start running again in the iterator method (also known as yield). In C Language /Java, it is comparable to continuing. It is optional for the following statement to supply a value that serves as the block’s outcome for that iteration.

break: Controls the statement that comes right after the iterator invocation, leaving the block and the iterator method that called it. It is optional for the break statement to supply a value that serves as the iterator invocation’s return value.

return: The lexically enclosing method (the method the block is specified within in the source code) exits along with the block and the iterator when return occurs inside a block, unlike in nested functions in certain other languages.

Code Example ( in an Iterator)

(1..4).each do |item|
  # Skip processing for even numbers
  next if item.even? 
  puts "Item: #{item}"
end

Output

Item: 1
Item: 3

/ Blocks

Begin/end blocks are another control structure that Ruby employs to arrange several statements, apart from the code blocks linked to methods.

The value of the final statement run inside the begin block is returned by the begin block. When used in conjunction with exception handling clauses like rescue, else, and ensure, or for conditional assignments (||=), these blocks are especially helpful.

Important Distinction: It is not possible to send begin blocks to functions; they are not the same as do…end or {} code blocks. The begin keyword is frequently not required for exception handling when defining methods, modules, or classes because the block boundary is provided by the def, module, or class structure.

Code Example (/)

puts begin
  1
  2
  3
end

Output

3
Agarapu Geetha
Agarapu Geetha
My name is Agarapu Geetha, a B.Com graduate with a strong passion for technology and innovation. I work as a content writer at Govindhtech, where I dedicate myself to exploring and publishing the latest updates in the world of tech.
Index