Thanks for linking this. I'd only glanced at refinements so far... reading these comments and example code makes my head hurt. I wouldn't have thought "solving" monkey-patching with something even more convoluted and confusing was even possible. My favorite code example is from tenderlove:
class Foo < SomeParent
def baz(str)
cached = str.camelize
ary.map {|name| cached + name}
end
end
Could have a completely different meaning than this code:
class Foo < SomeParent
def baz(str)
ary.map {|name| str.camelize + name}
end
end
I wish 2.0 had focused on speed, not a bunch of features that working rubyists really don't care about. Esp. not ones this poorly thought out (you'd think given 2 years discussion they would have abandoned the idea).
The decision making in the Ruby world seems to be fairly centralized and not very inclusive. To see that one of core devs of one of the biggest Ruby implementations thinks it's a bad idea is really confusing to me. I really wish there had been more discussion about it before it happened.
Cause now not only do we have that confusing feature which very few people seem to like, it also underlines a worrying trend where the different parts of the Ruby world don't reach a consensus before going in radical directions.
Refinements are not yet a part of Ruby 2.0 and their implementation in Ruby 2.0 is still under discussion. As Akira Matsuda pointed out @ the same RubyConf: "Warning: Refinements are experimental and may be removed from Ruby 2.0!" [23:15]
While I enjoyed most of Brian's talk, I wasn't particularly convinced by his dislike of refinements. Essentially, it boiled down to "this feature is hard to implement, it hides complexity, and it isn't well specified". The first and third arguments shouldn't matter to us nearly as much as the middle one. And I fail to see how namespacing monkey patches can do anything but decrease and contain accidental complexity (in the same way that method dispatch and polymorphism are better at limiting complexity than explicit conditionals).
The benefit to refinements is in preventing code conflicts from a shared namespace (like monkeypatching a core class).
The downside is it becomes even _harder_ to figure out what code is being run just by reading it. Right now, you just have superclasses and included modules, potentially gummed up by method_missing. Now, you need to also pay attention to refinements included by code that _calls_ the code you're looking at, which may change the way it behaves.
Unless used with great care, it's going to create a nightmare debugging situation. And with some of the code I've seen, it'll happen.
Speed and Memory usage. Both needs a huge improvement. And i could not understand why they are even trying with mRuby.
( I mean have they not heard of a thing called Lua and LuaJIT? )
Hopefully a lot of the tweaks and refinement will come from now to Final 2.0 release.
> And i could not understand why they are even trying with mRuby. ( I mean have they not heard of a thing called Lua and LuaJIT? )
LuaJIT is pretty much impossible in a language with as complex semantics as Ruby (it's probably impossible in Python already, and Ruby is significantly more complex)
I don't much like refinements, but conflicting monkey patches from different third party libraries _has_ been an issue over the years.
The ruby community is not even the first one to notice that, there is plenty of literature on "selector namespaces" and "classboxes" from the smalltalk crowd.
It has been an issue, but the much less painful solution is to be more careful about monkey patches, and employ other patterns whenever possible.
In my eyes, monkey patching should only ever be considered:
1. To fix outright bugs or nasty performance issues, where the monkey patch should not have other side effects.
2. In application code, never in libraries (except as a library explicitly providing monkey patches to an application, but never as a requirement for a library to work).
3. In adding new methods, except for case 1.
Of course there'd be exceptions, but very little monkey patching I see in library code is necessary or worth it.
Inside your library, you have plenty of ways of avoiding the need: Wrap objects; convert objects; use helpers. Yes, it might not look as perfectly smooth, but I'd take that over trying to reason about code that relies on different sets of refinements in different scopes any day..
From a language designer's perspective, conflicting monkey patches seem like a problem. But if you ask Ruby users I bet 90%+ would say speed and memory usage are much bigger problems.
Headius technical comments on ruby tracker are a must-read.
As my personal take, I am appalled at refinements. I think this is a bad idea solving the wrong problem.