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.hink 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 ando1 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-block code 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.