On Jan 26, 2011, at 12:49 AM, Charles Oliver Nutter wrote:
On Mon, Jan 24, 2011 at 11:13 AM, Joshua Ballanco <jballanc@gmail.com> wrote:
Regarding the potential bug...well...where to begin? So, yes, MacRuby blocks have the same semantics as regular Ruby blocks, *except* when they are dispatched through GCD. In that case, ivars are shared, but local variable get copied. I'm sure Laurent can explain why better than I, but it has to do with the semantics of libdispatch and the uncertainty inherent in when a dispatched block or function will execute (i.e. if local variables were not copied during dispatch, they might go out of scope and be collected before GCD ever gets around to running the code).
Wow, that's very surprising. I'm not sure I agree with bending Ruby semantics so drastically, even to help concurrency. Or at least, I'd expect other threaded scenarios to be consistent:
~ ➔ ruby -ve "a = 0; Thread.new { a += 1 }.join; p a" MacRuby 0.8 (ruby 1.9.2) [universal-darwin10.0, x86_64] 1
~ ➔ ruby -ve "a = 0; q = Dispatch::Queue.concurrent; q.sync {a += 1}; p a" MacRuby 0.8 (ruby 1.9.2) [universal-darwin10.0, x86_64] 0
The implicitness in being able to mutate the surrounding scope is certainly problematic. This is one reason Java's anonymous inner classes require that referenced variables be declared final...to indicate they can't be mutated by the body of the anonymous inner class's methods.
The result is that people end up using one-element arrays and the like, but people find ways around anything.
So I suppose this applies to anything in the surrounding scope, including visibility, $~, and so on?
No, only locals and dynamic (block) variables. To be honest I always disliked this semantic change too. I think it was a mistake to add it. It will probably be reverted for 1.0. Laurent