support@90-10.dev

Advanced Techniques with Ruby Blocks

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.

Here are couple of advanced techniques that you can use to get the most out of them:

Lambda vs. Proc

In Ruby, there are two types of blocks: lambdas and Procs. While they are similar in many ways, there are some important differences. For example, a lambda is more strict about the number of arguments it receives, while a Proc is more flexible. Here's an example:

def test_lambda
  lambda { |x| puts x }
end

def test_proc
  Proc.new { |x| puts x }
end

l = test_lambda
p = test_proc

l.call(1) # prints 1
p.call(1) # prints 1

l.call(1, 2) # ArgumentError: wrong number of arguments (2 for 1)
p.call(1, 2) # prints 1

In this example, test_lambda and test_proc are methods that return a lambda and a Proc, respectively. The lambda is more strict about the number of arguments it receives, while the Proc is more flexible.

Closures

A closure is a block of code that captures the environment in which it was defined. This means that it has access to variables and methods that were defined in the same scope. Here's an example:

def make_counter(start)
  lambda { start += 1 }
end

c1 = make_counter(0)
c2 = make_counter(10)

puts c1.call # prints 1
puts c1.call # prints 2
puts c2.call # prints 11
puts c2.call # prints 12

In this example, make_counter is a method that returns a lambda. The lambda captures the value of start when it was defined, and increments it each time it is called. This allows you to create multiple counters that operate independently.

Lazy Evaluation

Lazy evaluation is a technique that allows you to defer the evaluation of a block until it is needed. This can be useful for improving performance or conserving resources. Here's an example:

def lazy(&block)
  Enumerator.new do |yielder|
    loop { yielder.yield(block.call) }
  end.lazy
end

numbers = lazy { rand(100) }

puts numbers.take(10).to_a.join(", ")

In this example, lazy is a method that takes a block and returns a lazy Enumerator. The block is evaluated each time an element is requested from the Enumerator using the take method. This allows you to generate a potentially infinite sequence of values without actually generating them all at once.


Ruby blocks are a powerful feature of the language and 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.