LaunchKit
All quizzes
Ruby 0 views

Two yields, one block

Question

What is the return value of the following Ruby code?

def sum
  n = 0

  n += yield
  n += yield

  n
end

sum { 42 } # => ???

The correct answer is

Explanation

TL;DR

yield invokes the block passed to the method, once per yield reached at runtime. The block { 42 } returns 42 on every invocation, so n goes from 0 to 42 to 84, and the method returns 84.

Step by step

def sum
  n = 0

  n += yield # n: 0 + 42
  n += yield # n: 42 + 42

  n
end

sum { 42 } # => 84

A block is not consumed by the first yield. It stays attached to the method call, and every yield runs it again:

def multiple_yields
  yield
  yield
end

multiple_yields { puts "multiple yields" }

Output:

multiple yields
multiple yields

Edge cases

yield accepts arguments, which become the block's parameters. Each invocation can pass different values:

def sum
  n = 0
  n += yield(1)
  n += yield(10)
  n
end

sum { |x| x * 2 } # => 22

Calling a method that yields without passing a block raises LocalJumpError:

def sum
  n = 0
  n += yield
  n
end

begin
  sum
rescue LocalJumpError => e
  e.message # => "no block given (yield)"
end

Guard with block_given? when the block is optional:

def sum
  return 0 unless block_given?
  yield + yield
end

sum        # => 0
sum { 21 } # => 42

Share this quiz

Comments

No comments yet. Be the first.

Only used to confirm and publish your comment. Never shown publicly, never shared.

Markdown: **bold**, `code`, ```fenced blocks```, > quotes, [links](url). HTML and images are not rendered.