3

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 )

5
  • 3
    Doesn't that mean that the return returns from your test function, making it pass without reaching the assertions at all? Commented Apr 20, 2011 at 16:12
  • It does indeed. '1 tests, 0 assertions, 0 failures, 0 errors' Commented Apr 20, 2011 at 16:25
  • So then it's not reaching your second call to iterate... Commented Apr 20, 2011 at 16:41
  • 1
    I tested both 1.8.7 and 1.9.2 and both don't reach first assert_equal, which is expected, as return in your first block returns from the method. Commented Apr 20, 2011 at 17:42
  • Correct, This was a simple oversight on my part. Hammar correctly stated the return statement in the first test exits the 'test_iterate' block. Altho it appeared that the test passed, infact the test never completed. Commented Apr 25, 2011 at 17:04

1 Answer 1

4

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
Sign up to request clarification or add additional context in comments.

1 Comment

This is an acceptable way of allowing the tests to pass. Answer is accepted.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.