yield and blocks

321 views

What is the return value of the following Ruby 3 code?

def method1
  yield
end

def method2
end

method1 { A = :file1 }
method2 { B = :file2 }

[A, B] # => ???

The correct answer is

uninitialized constant A

uninitialized constant B

[:file1, nil]

[nil, :file2]

Unlock Your Ruby Potential

Subscribe to RubyCademy and get free access to all our courses, plus hundreds of fun Ruby cards, quizzes, guides, and tutorials!

Explanation

Let's break down the provided example:

def method1
  yield
end

def method2
end

method1 { A = :file1 }
method2 { B = :file2 }

[A, B] # => ??? # => uninitialized constant B (NameError)

In this code, method1 is defined to accept a block and then yields to that block. method2 is defined but does not take a block or do anything.

When method1 is called with a block { A = :file1 }, the symbol :file1 is assigned to the constant A.

Since blocks do not isolate the scope of constants, A becomes a globally accessible constant.

When method2 is called with a similar block { B = :file2 }, nothing happens because method2 does not yield to the block, meaning B is never defined.

As a result, attempting to access [A, B] will raise a NameError because B is not initialized, while A remains defined globally.

Warning

Do not define constants within a block, as the block's scope does not isolate or namespace the constant in any way.

This can lead to issues where constants are unexpectedly available globally or cause errors when they are referenced before being defined.

Instead, define constants outside of the block if they need to be globally accessible, or use a local variable or method if the scope should be limited to within the block

task :zip_files do
  files_to_zip = Dir['logs/*.log']

  # Zip logic here
end

Here, files_to_zip is a local variable, properly scoped to only be accessible within the block, which avoids the risks associated with defining constants globally.

Check out our latest eBook if you enjoy fun Ruby code examples with clear insights! 🙏

🔗 RubyCademy Cards - 1st Edition

Voilà!

Unlock Your Ruby Potential

Subscribe to RubyCademy and get free access to all our courses, plus hundreds of fun Ruby cards, quizzes, guides, and tutorials!

RubyCademy ©