On Mon, Nov 05, 2012 at 02:17:49PM +0900, headius (Charles Nutter) wrote:
> 
> Issue #4085 has been updated by headius (Charles Nutter).
> 
> 
> I currently don't see any way to support enabling refinements in blocks without a global, unavoidable impact to all call sites.
> 
> If refinements are applied lexically, then a block suddenly having refinements active does not make sense, since the code in the block is not lexically surrounded by a scope with active refinements.
> 
> If refinements are applied based on the cref module, then a block still can't see them because cref for the block is determined lexically. This was explicitly done to allow constant lookup to always proceed based on lexical scopes.
> 
> Formally, the clearest way for refinements to work is for you to explicitly opt into them everywhere you want to use them. A couple thoughts about different forms:
> 
> 1. using as a scope-opening keyword like "class" or "module":
> 
> using RSpec
>   describe "Some Spec" do
>     it "does some RSpec things" do # "it" comes from refinements
>       'foo'.should == 'foo' # "should" comes from refinements
>     end
>   end
> end
> 
> This is clear to the user and the parser that all calls downstream from the "using" must consider refinements. They would see the refinements based on cref (or something similar) because of the explicit nesting of scopes.
> 
> 2. "using" as a pseudo-keyword, affecting lexical scopes and code following "using"
> 
> using RSpec
> 
> describe "Some Spec" do
>   it "does some RSpec things" do # "it" comes from refinements
>      'foo'.should == 'foo' # "should" comes from refinements
>   end
> end
> 
> In this case, the parser could still treat all calls following "using" as needing refinements. This is less ideal, because it force us to treat all "using" calls everywhere in the system as potentially triggering refined call sites. It also makes it impossible to detect if "using" is ever aliased or sent. If such features are expected, we'd be back to treating all calls as refined all the time.
> 
> Honestly, I really believe that allowing refinements to affect scopes that have no "using" anywhere in sight is going to be really confusing, and it has the added pain of making efficient call site caching hard or impossible.

If I'm understanding you correctly, the thing I don't like about
explicitly requiring people to add "using" means that we can't remove
the monkey patches from Rails without breaking everything.

For example:

class MyModel < ActiveRecord::Base
  def foo
    # constantize comes from Rails monkey patches on String
    "somestring".constantize 
  end
end

Ideally, in the Rails source code, I would just add "using StringExt" to
the ActiveRecord::Base class, and the existing user code would Just
Work.  If existing Rails users are required to add the "using" word to
all of their code, then there is no way we (the rails team) can remove
the monkey patches and remain backwards compatible.

Being able to remove monkey patches and remain backwards compatible is
the number one most important thing I want from refinements.

-- 
Aaron Patterson
http://tenderlovemaking.com/