DEV Community

Andrew Lee
Andrew Lee

Posted on

Understanding Blocks in Ruby

One of Ruby's defining features is a block. A block can either be surrounded by { } or do end.

# Use { } for single line commands
3.times { puts "Hello"}

# Use do end for multi line commands
3.times do
  puts "Hello"
end
Enter fullscreen mode Exit fullscreen mode

The key to understanding blocks is the yield keyword. We use the yield keyword in our method definition to defer to the block of code that was passed in.

Let's take a closer look by implementing our own version of the times method.

def my_times
  yield
  yield
  yield
end
Enter fullscreen mode Exit fullscreen mode

We can call this method with a block and it will execute the block three times.

my_times { puts "Hello" }
Enter fullscreen mode Exit fullscreen mode

We can do better. Let's define a my_times method for all instances of Integer.

class Integer
  def my_times
    i = 0
    while i < self
      yield
      i += 1
    end
  end
end

Enter fullscreen mode Exit fullscreen mode

Now we can call our my_times method on an instance of Integer just like the original times method.

3.times { puts "Hello" }
3.my_times { puts "Hello" }
Enter fullscreen mode Exit fullscreen mode

We can pass in arguments to a block as well. We might have seen this with the each method:

[1, 2, 3].each { |x| puts x }
Enter fullscreen mode Exit fullscreen mode

We can write our own my_each method like the following:

class Array
  def my_each
    i = 0
    while i < self.length
      yield(self[i])
      i += 1
    end
    self
  end
end
Enter fullscreen mode Exit fullscreen mode
[1, 2, 3].each { |x| puts x }
[1, 2, 3].my_each { |x| puts x }
Enter fullscreen mode Exit fullscreen mode

Top comments (0)