Project

General

Profile

Actions

Feature #9696

closed

More Flexible Refinement Syntax

Added by trans (Thomas Sawyer) about 10 years ago. Updated over 8 years ago.

Status:
Rejected
Assignee:
-
Target version:
-
[ruby-core:61818]

Description

I am the maintainer of Ruby Facets, the core extensions library. For the next release of Facets I have long planned to provide support for Refinements. Unfortunately, after working with the code to determine what would be necessary to support them, I've come to the conclusion that it's just not reasonable to do so. The problem lies in the fact that Facets must still be backward compatible with it's "monkey-patch" usage. In fact, that usage is sometimes preferable b/c you can require once and don't have to write using Foo in every file that a core extension might be needed. But, b/c of the syntax that refinements use, to support both patching and refining I would have to maintain TWO COPIES of every extension, which simply isn't practical.

For example, the normal definition of a String#foo:

class String
  def foo
    ...
  end
end

And the refinement:

module Facets
  refine String do
    def foo
      ...
    end
  end
end

There does not appear to be any reasonable way to have the definition defined once and still be able to be use it in either manner. (Also, I want to point out that refinements do not lend themselves to cherry picking specific methods per-file either.)

So, unless someone has a clever approach that I have not thought of, I wonder if it would not be a good idea to reconsider the syntax of refinements. Would it be possible to simplify the definition to use class instead of refine, e.g.

module Facets
  class String
    def foo
      ...
    end
  end
end

And then allow using Facets which would refine any common class is the scope. And further, allowing also using Facets::String and even using Facets::String::foo to cherry pick refinements? In addition, a way to "apply" a module as if it were evaluated in the scope. This would then allow the same code to be used either as a refinement or as an extension.

Alternatively, maybe refinements should just be a require --if they will forever remain at the file-level. Then no special syntax would be needed at all. Simply defining them in a separate file, e.g.

# string/foo.rb
class String
  def foo
    ...
  end
end

And then "using" them by file name instead would do the trick.

using 'string/foo'
Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0