Details
-
Type:
Bug
-
Status:
Closed
-
Priority:
Minor
-
Resolution: Fixed
-
Affects Version/s: JRuby 1.0.0
-
Fix Version/s: JRuby 1.1.4
-
Component/s: Interpreter
-
Labels:None
-
Environment:JRuby 1.0.0-2 on Debian/sid
-
Number of attachments :
Description
Charles Oliver Nutter was discussing JRuby's "break" semantics on user@groovy.codehaus.org, when he said the following:
> Generally break would terminate the nearest enclosing loop. Since times
> and each are implemented in terms of a loop, they would terminate. If
> the closure passed to them contained a call to some other looping
> structure, that looping structure would terminate.
So I decided that I'd try a recursive version, since it should make no difference to the user whether each is implemented recursively or iteratively. As a result, I discovered a difference between JRuby and MRI
def my_each array, index, &block return self if index==array.length block.call(array[index]) my_each array, index+1, &block puts array[index] end my_each([1,2,3,4],0) do |x| break if x==3 puts x end
In MRI, this prints:
1 2
In JRuby, it breaks:
1
2
-:3:in `my_each': break from proc-closure (LocalJumpError)
from -:4:in `my_each'
from -:12
On the other hand, the following also breaks in MRI
def my_each array, index, &block return self if index==array.length block.call(array[index]) my_each array, index+1, &block puts array[index] end x=Proc.new do |x| break if x==3 puts x end my_each([1,2,3,4],0, &x)
in MRI:
1
2
-:9:in `call': break from proc-closure (LocalJumpError)
from -:3:in `my_each'
from -:4:in `my_each'
from -:13
but it breaks differently in JRuby:
1
2
-:3:in `my_each': break from proc-closure (LocalJumpError)
from -:4:in `my_each'
from -:13
Apparently, in MRI, a break call breaks back to the lexical scope where the proc was declared if you didn't detatch the declaration from its use.
Thanks for this report Ken. We've chased around various inconsistencies in our implementation of Ruby's non-local flow control, and you have stumbled upon another difference. We'll see about getting it fixed for 1.1, and perhaps 1.0.2 if it's released before then.