Derrick J Wippler
Derrick J Wippler

Reputation: 323

Behavior of 'return' keyword within a ruby block

Can someone explain the behavior of the following

def iterate
  return yield
  return "end of iterate"
end

def test_iterate
  assert_equal( "end of iterate",  iterate { return "end of block" } )
  assert_equal( "end of block",  iterate { "end of block" } )
end

I understand that Procs ( Which is what blocks are ) should return within the scope they are called. ( Unlike lambdas ) With this in mind, shouldn't both calls in the tests return "end of block"?

This test passes on 'ruby 1.8.7 (2009-06-12 patchlevel 174) [universal-darwin10.0]' ( OSX 10.6.7 )

Upvotes: 3

Views: 1058

Answers (1)

Pedro Rolo
Pedro Rolo

Reputation: 29930

The return keyword returns from the lexicaly enclosing method. That is, *test_iterate*.

To return a certain value from a block in a dynamically scoped fashion, you should use the break keyword instead.

In your case:

iterate { break("end of block") }

The test will fail. because the second return statement of the iterate method will never run.

The intended semantics should be accomplished by using exceptions:

def iterate
  return yield
  rescue :exception
    return "end of iterate"
end

def test_iterate
  assert_equal( "end of iterate",  iterate { raise :exception } )
  assert_equal( "end of block",  iterate { "end of block" } )
end

Upvotes: 4

Related Questions