|
|
|
Revisiting this again...
The move of $~ and $_ to Frame isn't entirely wrong. What Ruby does is store it on the scope, but only on a "topmost" scope in a given scope's parent hierarchy. So a normal block will still share $~ slots with its containing method. I think the effect we're seeing here is that lambda is not reaching the correct frame on which to make these updates, which now produces the output: nil "a" "c" nil "a" "c" ...because the match only gets stored in the lambda's cloned frame, not in the original containing frame. And sub is also not storing the result into the correct frame. |
||||||||||||||||||||||||||||||||||||||||||||||
To fix this, should we choose to do so, we have a couple options:
(Regardless of the approach, we would have to put them back on the scope)
The frustrating detail here is that Ruby isn't consistently handling $~ and $_ as though they're local variables, since if the variable has not been assigned in a given child scope, Ruby checks the parent scope. Once set in the child scope, the parent scope is never used again. We've never had that behavior as far as I remember, and it's in my opinion a rather ugly wart.