Ruby Blocks
In Ruby, a block is a piece of code that can be executed. It is similar to a function or a method, but it is not an object. Blocks are used in many places in Ruby, such as iterators and callbacks. A block is a self-contained unit of code that can be passed around as a parameter to a method or another block. This is what makes them so powerful and versatile.
Syntax
A block is enclosed in curly braces {}
or do-end
. Here's an example of a block that prints the numbers from 1 to 5:
5.times { |i| puts i+1 }
The pipe symbol |
is used to define a parameter for the block. In this case, the parameter is i
. The block is executed 5 times, and each time it prints the value of i+1
.
The same block can be written using the do-end syntax:
5.times do |i|
puts i+1
end
The advantage of using the do-end
syntax is that it allows you to write multi-line blocks. This can make your code more readable, especially if the block contains a lot of code.
Passing Blocks to Methods
Blocks can be passed to methods as arguments. The method can then execute the block at a later time. Here's an example:
def repeat(n)
n.times { yield }
end
repeat(3) { puts "Hello" }
The repeat
method takes an argument n
and a block. The block is executed n
times using the yield
keyword. In this example, the block prints "Hello" 3 times.
Blocks can also be passed to methods using the &
operator. This operator converts a block into a Proc object, which can be passed as an argument to a method that expects a Proc. Here's an example:
def my_method(&block)
block.call
end
my_method { puts "Hello" }
The my_method
method takes a block as an argument and calls it using the call
method. The block prints "Hello" to the console.
Common Use Cases
Blocks are used in many places in Ruby. Here are a few common use cases:
Iterators
An iterator is a method that executes a block of code for each element in a collection. Here's an example:
[1, 2, 3].each { |i| puts i }
This code prints the numbers 1, 2, and 3 to the console. The each
method is an iterator that executes the block for each element in the array.
Callbacks
A callback is a method that is executed when a certain event occurs. Here's an example:
class MyClass
def initialize(&block)
@callback = block
end
def do_something
# do something
@callback.call
end
end
obj = MyClass.new { puts "Callback executed" }
obj.do_something # prints "Callback executed"
In this example, the MyClass
constructor takes a block as an argument and assigns it to an instance variable @callback
. The do_something
method does something and then executes the callback using the call
method.
DSLs (Domain-Specific Languages)
A DSL is a language that is specific to a certain domain or problem space. Blocks are often used to create DSLs in Ruby. Here's an example:
class MyDSL
def initialize(&block)
instance_eval(&block)
end
def hello(name)
puts "Hello, #{name}!"
end
end
MyDSL.new do
hello "John"
end
In this example, the MyDSL
constructor takes a block as an argument and evaluates it using the instance_eval
method. The block contains a call to the hello
method, which prints "Hello, John!" to the console.
Ruby blocks are a powerful feature of the language. They allow you to write concise and expressive code, and are used extensively in the standard library. Understanding how to use blocks is essential for any Ruby developer. With blocks, you can write code that is more flexible and reusable, and that can be used in a variety of contexts. So if you're new to Ruby, or if you haven't used blocks before, take some time to learn this important feature. And if you're already familiar with blocks, explore some of the advanced techniques that are available to you.