From: Rodrigo Rosenfeld Rosas Date: 2014-04-03T06:54:32-03:00 Subject: [ruby-core:61830] Re: [ruby-trunk - Feature #9696] [Open] More Flexible Refinement Syntax --001a11c3a9205490e104f62063c3 Content-Type: text/plain; charset=ISO-8859-1 For a practical solution you might be interested on you might build a preprocessor that would generate the duplicate files you need which could be ignored by your VCS but included in your gem. Em 03/04/2014 00:22, escreveu: > Issue #9696 has been reported by Thomas Sawyer. > > ---------------------------------------- > Feature #9696: More Flexible Refinement Syntax > https://bugs.ruby-lang.org/issues/9696 > > * Author: Thomas Sawyer > * Status: Open > * Priority: Normal > * Assignee: > * Category: core > * Target version: current: 2.2.0 > ---------------------------------------- > 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' > ~~~ > > > > > > -- > https://bugs.ruby-lang.org/ > --001a11c3a9205490e104f62063c3 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable

For a practical solution you might be interested on you migh= t build a preprocessor that would generate the duplicate files you need whi= ch could be ignored by your VCS but included in your gem.

Em 03/04/2014 00:22, <transfire@gmail.com> escreveu:
Issue #9696 has been reported by Thomas Sawyer.

----------------------------------------
Feature #9696: More Flexible Refinement Syntax
https:= //bugs.ruby-lang.org/issues/9696

* Author: Thomas Sawyer
* Status: Open
* Priority: Normal
* Assignee:
* Category: core
* Target version: current: 2.2.0
----------------------------------------
I am the maintainer of Ruby Facets, the core extensions library. For the ne= xt release of Facets I have long planned to provide support for Refinements= . Unfortunately, after working with the code to determine what would be nec= essary 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 stil= l be backward compatible with it's "monkey-patch" usage. In f= act, that usage is sometimes preferable b/c you can require once and don= 9;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 patchi= ng and refining I would have to maintain TWO COPIES of every extension, whi= ch simply isn't practical.

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

~~~
class String
=A0 def foo
=A0 =A0 ...
=A0 end
end
~~~

And the refinement:

~~~
module Facets
=A0 refine String do
=A0 =A0 def foo
=A0 =A0 =A0 ...
=A0 =A0 end
=A0 end
end
~~~

There does not appear to be any reasonable way to have the definition defin= ed once and still be able to be use it in either manner. (Also, I want to p= oint 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 wond= er 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
=A0 class String
=A0 =A0 def foo
=A0 =A0 =A0 ...
=A0 =A0 end
=A0 end
end
~~~

And then allow `using Facets` which would refine any common class is the sc= ope. And further, allowing also `using Facets::String` and even `using Face= ts::String::foo` to cherry pick refinements? In addition, a way to "ap= ply" a module as if it were evaluated in the scope. This would then al= low 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 fo= rever remain at the file-level. Then no special syntax would be needed at a= ll. Simply defining them in a separate file, e.g.

~~~
# string/foo.rb
class String
=A0 def foo
=A0 =A0 ...
=A0 end
end
~~~

And then "using" them by file name instead would do the trick.
~~~
using 'string/foo'
~~~





--
https://bugs.ruby= -lang.org/
--001a11c3a9205490e104f62063c3--