On 21.11.2012 07:15, shugo (Shugo Maeda) wrote:
> I'll remove it if permission granted by Matz.
>
>>   For now people can use Module.extended/.included if they really want to
>>   add refinement inheritance themselves.
>
> Currently this wouldn't work because you cannot get the caller context in these hooks.

What about the following?

   module RefinementInheritor
     def extended(base)
       base.send(:using, FooExt)
       # or
       base.module_eval "using FooExt"
     end
   end

>>   Probably the safest approach for now would be to use the source
>>   refinement scope (which is quasi-static) for module_eval by default and
>>   add a way to use the target scope (or an explicit scope) later on as
>>   needed. If there is any performance impact it would restricted to the
>>   target-scoped procs.
>
> Do you mean that a new option of module_eval should be introduced?
> For example,
>
>    Foo.module_eval { # use refinements in the current context }
>    Foo.module_eval(using_refinements: true) { # use refinements in the receiver }

I was thinking about

   Proc.new.rebind_refinements(TargetClass)

since this would only allow a single scope per proc at any given time 
which might make optimizations easier. But maybe your way would work too.

> Originally, String#bar was not visible in the Proc created by Symbol#to_proc.
> But I've changed it because Matz asked to do.  I think the current behavior
> is not consistent, but useful.
>
> If Symbol#to_proc were written in Ruby, it would be impossible, but
> Symbol#to_proc is written in C.  There are some such special methods.
> For example, Module.nesting returns the module nesting information in the
> caller context.  Module#using also affects the caller context.

So we need to special-case .to_proc. What happens when I 
alias-method-chain to_proc? Would it use the wrong scope? Would things 
break?

.__send__ and .method obviously suffer from the same issues of shifting 
stack frames and aliasing. Other metaprogramming things might be 
expected to do the "right thing(tm)" too and thus would have to rely on 
stack inspection which is an absolute minefield in Ruby.

Should the anonymous refinement module be mutable? E.g. by adding some 
respond_to_missing to it?

Has anyone even defined how metaprogramming should work with refinements?