Project

General

Profile

Feature #12086

using: option for instance_eval etc.

Added by shugo (Shugo Maeda) over 4 years ago. Updated 7 months ago.

Status:
Open
Priority:
Normal
Assignee:
-
Target version:
-
[ruby-core:73886]

Description

Currently refinements can be activated only in toplevel or class/module definitions.
If they can be activated in block-level, it's useful to implement internal DSLs.

How about to add a new option using: for Kernel#instance_eval and Moule#{class,module}_eval?

module FixnumDivExt
  refine Fixnum do
    def /(other)
      quo(other)
    end
  end
end

p 1 / 2 #=> 0
instance_eval(using: FixnumDivExt) do
  p 1 / 2 #=> (1/2)
end
p 1 / 2 #=> 0

Proof-of-concept implementation is available at https://github.com/shugo/ruby/tree/eval_using.

In my previous proposal before Ruby 2.0, refinements used in a class or module are
implicitly activated by instance_eval and class_eval, but now I think it's better to
explicitly specify refinements to be activated.

Considerations:

  • In the PoC implementation, refined methods are not cached inline, and thus it decreases the performance of refined method call. If there is a way to guarantee that blocks never be evaluated in different environments, refined methods can be cached inline.
  • {instance,class,module}_exec cannot be extended in the same way, because they take arbitrary arguments and there's no way to distinguish an option hash from the last argument hash.

Related issues

Related to Ruby master - Feature #12281: Allow lexically scoped use of refinements with `using {}` block syntaxAssignedshugo (Shugo Maeda)Actions
Related to Ruby master - Feature #16461: Proc#usingOpenActions

Also available in: Atom PDF