More thoughts...

I could get behind refinements if using were a keyword (so we could
tell at parse time refinements would be active) and purely lexical.
The following features of the current implementation would have to be
removed:

* refinements cascading down class hierarchies
* refinements affecting code in module_eval'ed blocks

If using became a keyword and purely lexical, the following examples
would be fine:

rails_thing.rb:

class Foo
  using ActiveRecord::SomeExt
  ...
end

rspec_thing.rb:

using RSpec

describe 'Refinements' do
  it 'should be purely lexical' do
...

If refinements can affect code outside the lexical scope where they
are activated, I believe it will be confusing, potentially dangerous,
very hard to debug, and potentially difficult or impossible to
implement without slowing all of Ruby down.

On Sat, Nov 3, 2012 at 10:38 AM, Charles Oliver Nutter
<headius / headius.com> wrote:
> On Fri, Nov 2, 2012 at 7:12 PM, shugo (Shugo Maeda)
> <redmine / ruby-lang.org> wrote:
>> headius (Charles Nutter) wrote:
>> > * Refinements in modules and class hierarchies does not seem like a problem to me yet.
>> > * Refinements are "used" in temporal order...methods added before "using" won't see refinements, refinements added after "using" won't be applied. I think this is a good thing, since it allows us to have a one-shot flag for refinements on methods at definition time.
>>
>> The current behavior is mainly for an implementation reason, but Matz and ko1 seem not to like it:(
>
> I commented on ko1's bug. I see using a bit like visibility changes,
> only affecting methods defined later on.
>
> I understand the implementation reason as well...in order to limit the
> damage of refinements, your impl flags methods as having refinements
> active. For optimization purposes, that means we know at definition
> time whether we need to handle refinements at all.
>
>> > * Months ago when the original proposal came out, I expressed my concern about refinements applying to module_eval and friends. I still strongly object to this behavior.
>>
>> I also wonder whether module_eval with blocks should be affected by refinements or not, but I think module_eval with strings (e.g., M.module_eval("C.new.foo")) has no problem, right?
>
> String eval would not be a problem, that is correct. We would be able
> to see at eval time that the target module has refinements active.
>
>> > This is dynamic application of refinements, which has been hotly debated and which I *thought* was supposed to be removed. I assume it has been left in because it is required to apply refinements "magically" to all-blockode like rspec. I do not see this as an excuse to introduce such an unpredictable feature.
>>
>> instance_eval and module_eval themselves have the same problem because they change self "magically".
>> At first, I thought they are evil, but they are popular now.
>> I'd like to ask Matz's opinion.
>
> Yes, module_eval, class_eval, and instance_eval are all problematic
> because of the self changing, but module_eval and class_eval are
> especially bad if they force refinements on code that doesn't know
> about them.
>
> I am starting to see some intractable problems with refinements, unfortunately.
>
> In order to avoid having every call in the system check for
> refinements, they are applied in evaluation order. However, this means
> that the load order of scripts can now completely change which methods
> get called. For example...
>
> a.rb:
>
> class Foo
>   def go(obj)
>     obj.something
>   end
> end
>
> b.rb:
>
> class Foo
>   using Baz # refines the "something" call
> end
>
> If the files are loaded in the order a, b, no refinements are applied
> to the something call. If b is loaded before a, refinements are
> applied to the something call. No other features in Ruby are so
> sensitive to load order (other than those that introspect classes and
> methods, obviously).
>
> The alternative is to have refinements not be applied temporally.
> However this means every call in the system needs to check for
> refinements every time. Given the complexity of method lookup in Ruby
> today, adding refinements to that process seems like a terrible idea.
>
> In order to cache a method call in the presence of refinements, we
> need to track all of the following:
>
> 1. whether any refinements are active
> 2. whether there are refinements that affect the class of the target
> of the method call
> 3. whether refinements that affect the target class redefine the target method
>
> If any of these change at any time, we need to invalidate the cache.
> This is on top of all the information we need to do to cache methods
> normally.
>
> At this point I would not vote for refinements to be included in Ruby
> 2.0. I feel like there are far too many edge cases and implementation
> concerns.
>
> I will continue my investigation.