ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
* [ruby-core:61818] [ruby-trunk - Feature #9696] [Open] More Flexible Refinement Syntax
       [not found] <redmine.issue-9696.20140403032155@ruby-lang.org>
@ 2014-04-03  3:21 ` transfire
  2014-04-03  9:54   ` [ruby-core:61830] " Rodrigo Rosenfeld Rosas
  2014-04-03  9:10 ` [ruby-core:61828] [ruby-trunk - Feature #9696] [Rejected] " matz
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 9+ messages in thread
From: transfire @ 2014-04-03  3:21 UTC (permalink / raw
  To: ruby-core

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/

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [ruby-core:61828] [ruby-trunk - Feature #9696] [Rejected] More Flexible Refinement Syntax
       [not found] <redmine.issue-9696.20140403032155@ruby-lang.org>
  2014-04-03  3:21 ` [ruby-core:61818] [ruby-trunk - Feature #9696] [Open] More Flexible Refinement Syntax transfire
@ 2014-04-03  9:10 ` matz
  2014-04-03  9:58 ` [ruby-core:61831] [ruby-trunk - Feature #9696] " rr.rosas
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: matz @ 2014-04-03  9:10 UTC (permalink / raw
  To: ruby-core

Issue #9696 has been updated by Yukihiro Matsumoto.

Status changed from Open to Rejected

In that case, string/foo.rb will work differently loaded by #using or #require.
I don't think it is a good design, although I admit there could be better design.

Matz.


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

* Author: Thomas Sawyer
* Status: Rejected
* 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/

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [ruby-core:61830] Re: [ruby-trunk - Feature #9696] [Open] More Flexible Refinement Syntax
  2014-04-03  3:21 ` [ruby-core:61818] [ruby-trunk - Feature #9696] [Open] More Flexible Refinement Syntax transfire
@ 2014-04-03  9:54   ` Rodrigo Rosenfeld Rosas
  0 siblings, 0 replies; 9+ messages in thread
From: Rodrigo Rosenfeld Rosas @ 2014-04-03  9:54 UTC (permalink / raw
  To: Ruby developers

[-- Attachment #1: Type: text/plain, Size: 3050 bytes --]

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, <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
> 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/
>

[-- Attachment #2: Type: text/html, Size: 3681 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [ruby-core:61831] [ruby-trunk - Feature #9696] More Flexible Refinement Syntax
       [not found] <redmine.issue-9696.20140403032155@ruby-lang.org>
  2014-04-03  3:21 ` [ruby-core:61818] [ruby-trunk - Feature #9696] [Open] More Flexible Refinement Syntax transfire
  2014-04-03  9:10 ` [ruby-core:61828] [ruby-trunk - Feature #9696] [Rejected] " matz
@ 2014-04-03  9:58 ` rr.rosas
  2014-04-03 15:20 ` [ruby-core:61840] " transfire
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: rr.rosas @ 2014-04-03  9:58 UTC (permalink / raw
  To: ruby-core

Issue #9696 has been updated by Rodrigo Rosenfeld Rosas.


 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, <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
 > 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/
 >

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

* Author: Thomas Sawyer
* Status: Rejected
* 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/

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [ruby-core:61840] [ruby-trunk - Feature #9696] More Flexible Refinement Syntax
       [not found] <redmine.issue-9696.20140403032155@ruby-lang.org>
                   ` (2 preceding siblings ...)
  2014-04-03  9:58 ` [ruby-core:61831] [ruby-trunk - Feature #9696] " rr.rosas
@ 2014-04-03 15:20 ` transfire
  2014-04-03 16:55 ` [ruby-core:61844] " rr.rosas
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: transfire @ 2014-04-03 15:20 UTC (permalink / raw
  To: ruby-core

Issue #9696 has been updated by Thomas Sawyer.


If there "could be better design" could this ticket be set to feedback? Maybe others have some ideas about it. 

Am I wrong to think that the most applicable use-cases for refinements by-far are the ActiveSupport and Facets core extension libraries? And if those two projects find it impractical to support refinements, then a better solution really does need to be found. Otherwise refinements will simply be an unused (hence useless) feature.

@Rodrigo Thanks for the suggestion. I have considered that. While most extensions would work fine, edge cases tend to make maintaining such a pre-processor a real headache. I won't rule it out, but that's not an approach I'd readily jump into.


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

* Author: Thomas Sawyer
* Status: Rejected
* 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/

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [ruby-core:61844] [ruby-trunk - Feature #9696] More Flexible Refinement Syntax
       [not found] <redmine.issue-9696.20140403032155@ruby-lang.org>
                   ` (3 preceding siblings ...)
  2014-04-03 15:20 ` [ruby-core:61840] " transfire
@ 2014-04-03 16:55 ` rr.rosas
  2014-04-03 23:16 ` [ruby-core:61848] " matz
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: rr.rosas @ 2014-04-03 16:55 UTC (permalink / raw
  To: ruby-core

Issue #9696 has been updated by Rodrigo Rosenfeld Rosas.


I gave it a try here: https://gist.github.com/rosenfeld/9958332

If you keep your files simple it should be somewhat easy to generate the refinement versions from the original monkey patches...

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

* Author: Thomas Sawyer
* Status: Rejected
* 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/

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [ruby-core:61848] [ruby-trunk - Feature #9696] More Flexible Refinement Syntax
       [not found] <redmine.issue-9696.20140403032155@ruby-lang.org>
                   ` (4 preceding siblings ...)
  2014-04-03 16:55 ` [ruby-core:61844] " rr.rosas
@ 2014-04-03 23:16 ` matz
  2015-11-02 23:13 ` [ruby-core:71301] [Ruby trunk " james
  2015-11-02 23:17 ` [ruby-core:71302] " james
  7 siblings, 0 replies; 9+ messages in thread
From: matz @ 2014-04-03 23:16 UTC (permalink / raw
  To: ruby-core

Issue #9696 has been updated by Yukihiro Matsumoto.


Thomas, although I don't deny the possibility of "more flexible refinement syntax", I prefer creating new issues for each design proposals, so that we can refer them by issue numbers.  Please resubmit if you have new idea.


Matz.

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

* Author: Thomas Sawyer
* Status: Rejected
* 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/

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [ruby-core:71301] [Ruby trunk - Feature #9696] More Flexible Refinement Syntax
       [not found] <redmine.issue-9696.20140403032155@ruby-lang.org>
                   ` (5 preceding siblings ...)
  2014-04-03 23:16 ` [ruby-core:61848] " matz
@ 2015-11-02 23:13 ` james
  2015-11-02 23:17 ` [ruby-core:71302] " james
  7 siblings, 0 replies; 9+ messages in thread
From: james @ 2015-11-02 23:13 UTC (permalink / raw
  To: ruby-core

Issue #9696 has been updated by James Adam.


It *might* be possible to support both monkey-patching and refinements with a combination of modules, using prepend and refine:

~~~
class Target
end

# actual code
module Behaviour
  def new_method
    'facets-supplied behaviour'
  end
end
~~~

In 'facets/refinements.rb' you could define the following:

~~~
# refinement support
module Refinement
  refine Target do
    include Behaviour
  end
end
~~~

And then use it as follows:

~~~
require 'facets/refinements'
using Refinement
Target.new.new_method # => 'facets-supplied behaviour'
~~~

To use the same code via monkey-patching, use `prepend`; in 'facets/monkey-patch.rb':

~~~
# monkey-patch support
Target.send(:prepend, Behaviour)
~~~

And then to use it:

~~~
require 'facets/monkey-patch'
Target.new.new_method # => 'facets-supplied behaviour
~~~

Using `prepend` allows the module method definitions to take precedence over methods defined in the original class.

There's one significant problem doing this, which is that when you include a module via `refine`, methods in that module cannot call other methods within that module. I believe this is a simple artefact of the lexical scope of those method definitions, but it probably does make it impractical to use this technique for very sophisticated changes.

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

* Author: Thomas Sawyer
* Status: Rejected
* Priority: Normal
* Assignee: 
----------------------------------------
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/

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [ruby-core:71302] [Ruby trunk - Feature #9696] More Flexible Refinement Syntax
       [not found] <redmine.issue-9696.20140403032155@ruby-lang.org>
                   ` (6 preceding siblings ...)
  2015-11-02 23:13 ` [ruby-core:71301] [Ruby trunk " james
@ 2015-11-02 23:17 ` james
  7 siblings, 0 replies; 9+ messages in thread
From: james @ 2015-11-02 23:17 UTC (permalink / raw
  To: ruby-core

Issue #9696 has been updated by James Adam.


Another alternative is to slightly abuse the fact that refinements are also modules:

~~~
module Refinement
  Behaviour = refine Target do
    def new_method
      'facets-supplied-behaviour'
    end
  end
end
~~~

To use as a refinement:

~~~
using Refinement
Target.new.new_method # => 'facets-supplied behaviour'
~~~

To use via monkey-patching:

~~~
Target.send(:prepend, Refinement::Behaviour)
Target.new.new_method # => 'facets-supplied behaviour'
~~~

Using the module returned by `refine` in this way seems a bit risky, but it appears to work.

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

* Author: Thomas Sawyer
* Status: Rejected
* Priority: Normal
* Assignee: 
----------------------------------------
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/

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2015-11-02 22:48 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <redmine.issue-9696.20140403032155@ruby-lang.org>
2014-04-03  3:21 ` [ruby-core:61818] [ruby-trunk - Feature #9696] [Open] More Flexible Refinement Syntax transfire
2014-04-03  9:54   ` [ruby-core:61830] " Rodrigo Rosenfeld Rosas
2014-04-03  9:10 ` [ruby-core:61828] [ruby-trunk - Feature #9696] [Rejected] " matz
2014-04-03  9:58 ` [ruby-core:61831] [ruby-trunk - Feature #9696] " rr.rosas
2014-04-03 15:20 ` [ruby-core:61840] " transfire
2014-04-03 16:55 ` [ruby-core:61844] " rr.rosas
2014-04-03 23:16 ` [ruby-core:61848] " matz
2015-11-02 23:13 ` [ruby-core:71301] [Ruby trunk " james
2015-11-02 23:17 ` [ruby-core:71302] " james

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).