* [ruby-core:101278] [Ruby master Bug#17374] Refined methods aren't visible from a refinementRefinements that include/prepend module
@ 2020-12-07 5:25 marcandre-ruby-core
2020-12-07 5:26 ` [ruby-core:101279] [Ruby master Bug#17374] Refined methods aren't visible from a refinement's module marcandre-ruby-core
` (15 more replies)
0 siblings, 16 replies; 17+ messages in thread
From: marcandre-ruby-core @ 2020-12-07 5:25 UTC (permalink / raw
To: ruby-core
Issue #17374 has been reported by marcandre (Marc-Andre Lafortune).
----------------------------------------
Bug #17374: Refined methods aren't visible from a refinementRefinements that include/prepend module
https://bugs.ruby-lang.org/issues/17374
* Author: marcandre (Marc-Andre Lafortune)
* Status: Open
* Priority: Normal
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN
----------------------------------------
--
https://bugs.ruby-lang.org/
^ permalink raw reply [flat|nested] 17+ messages in thread
* [ruby-core:101279] [Ruby master Bug#17374] Refined methods aren't visible from a refinement's module
2020-12-07 5:25 [ruby-core:101278] [Ruby master Bug#17374] Refined methods aren't visible from a refinementRefinements that include/prepend module marcandre-ruby-core
@ 2020-12-07 5:26 ` marcandre-ruby-core
2020-12-07 10:25 ` [ruby-core:101283] " eregontp
` (14 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: marcandre-ruby-core @ 2020-12-07 5:26 UTC (permalink / raw
To: ruby-core
Issue #17374 has been updated by marcandre (Marc-Andre Lafortune).
Subject changed from Refined methods aren't visible from a refinementRefinements that include/prepend module to Refined methods aren't visible from a refinement's module
Is this intentional?
```
class Foo
module Extension
module Implementation
def foo
super(bar) # << Can not see bar
end
def bar # << Bar is in the same module!
42
end
end
refine Foo do
prepend Implementation
end
end
def foo(value = :none)
p value
end
end
Foo.new
Foo.new.foo # => :none (ok)
# Does not work: undefined local variable or method `bar'
using Foo::Extension
Foo.new.foo rescue :error # => :error
# Works:
Foo.prepend Foo::Extension::Implementation
Foo.new.foo # => 42
```
----------------------------------------
Bug #17374: Refined methods aren't visible from a refinement's module
https://bugs.ruby-lang.org/issues/17374#change-88957
* Author: marcandre (Marc-Andre Lafortune)
* Status: Open
* Priority: Normal
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN
----------------------------------------
--
https://bugs.ruby-lang.org/
^ permalink raw reply [flat|nested] 17+ messages in thread
* [ruby-core:101283] [Ruby master Bug#17374] Refined methods aren't visible from a refinement's module
2020-12-07 5:25 [ruby-core:101278] [Ruby master Bug#17374] Refined methods aren't visible from a refinementRefinements that include/prepend module marcandre-ruby-core
2020-12-07 5:26 ` [ruby-core:101279] [Ruby master Bug#17374] Refined methods aren't visible from a refinement's module marcandre-ruby-core
@ 2020-12-07 10:25 ` eregontp
2020-12-07 18:22 ` [ruby-core:101288] " marcandre-ruby-core
` (13 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: eregontp @ 2020-12-07 10:25 UTC (permalink / raw
To: ruby-core
Issue #17374 has been updated by Eregon (Benoit Daloze).
I think so. Refined methods only see each other if they are directly defined in the `refine`.
Using `prepend`/`include` is probably not recommended anyway, it leads to many complications in the semantics.
----------------------------------------
Bug #17374: Refined methods aren't visible from a refinement's module
https://bugs.ruby-lang.org/issues/17374#change-88961
* Author: marcandre (Marc-Andre Lafortune)
* Status: Open
* Priority: Normal
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN
----------------------------------------
--
https://bugs.ruby-lang.org/
^ permalink raw reply [flat|nested] 17+ messages in thread
* [ruby-core:101288] [Ruby master Bug#17374] Refined methods aren't visible from a refinement's module
2020-12-07 5:25 [ruby-core:101278] [Ruby master Bug#17374] Refined methods aren't visible from a refinementRefinements that include/prepend module marcandre-ruby-core
2020-12-07 5:26 ` [ruby-core:101279] [Ruby master Bug#17374] Refined methods aren't visible from a refinement's module marcandre-ruby-core
2020-12-07 10:25 ` [ruby-core:101283] " eregontp
@ 2020-12-07 18:22 ` marcandre-ruby-core
2020-12-07 18:58 ` [ruby-core:101290] " eregontp
` (12 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: marcandre-ruby-core @ 2020-12-07 18:22 UTC (permalink / raw
To: ruby-core
Issue #17374 has been updated by marcandre (Marc-Andre Lafortune).
Eregon (Benoit Daloze) wrote in #note-2:
> I think so. Refined methods only see each other if they are directly defined in the `refine`.
They can be defined in different `refine` blocks and it still works:
```ruby
class Foo
module Extension
refine Foo do
def foo
super(bar)
end
end
refine Foo do
def bar
42
end
end
end
def foo(value = :none)
p value
end
end
using Foo::Extension
Foo.new.foo # => 42
```
> Using `prepend`/`include` is probably not recommended anyway, it leads to many complications in the semantics.
It's not clear to me why they are allowed if they are supported this way.
I know of no other case in Ruby where two methods in a module can not see each other.
I know of no other case in Ruby where you can not extract some code in a new method (assuming no naming conflict)
Let's say a class does not define any methods; I know of no other case in Ruby where `include Mod` or copy-pasting `Mod`'s methods is different.
In my mind, `include/prepend` inserts a layer inside a Module and brings in those methods in it. I can not explain mentally what `refine { include }` does currently.
Here's a simplified example, where a method does not see itself:
```
module Extension
module Implementation
def foo(value = nil)
return value.to_s if value
foo(42) # => NoMethodError!?
end
end
refine Object do
include Implementation
end
end
using Extension
:x.foo(:y) # => 'y' (ok)
:x.foo # => NoMethodError
```
Finally, my use case is that I think it would be worthwhile to provide a way to write libraries that can be used either as a refinement, or as a apply everywhere:
```ruby
# Either
using MySuperGem # => everywhere you use the refinement
# Or
SomeClass.prepend MySuperGem # => once
```
This is *much* harder to write with the current semantics.
----------------------------------------
Bug #17374: Refined methods aren't visible from a refinement's module
https://bugs.ruby-lang.org/issues/17374#change-88972
* Author: marcandre (Marc-Andre Lafortune)
* Status: Open
* Priority: Normal
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN
----------------------------------------
--
https://bugs.ruby-lang.org/
^ permalink raw reply [flat|nested] 17+ messages in thread
* [ruby-core:101290] [Ruby master Bug#17374] Refined methods aren't visible from a refinement's module
2020-12-07 5:25 [ruby-core:101278] [Ruby master Bug#17374] Refined methods aren't visible from a refinementRefinements that include/prepend module marcandre-ruby-core
` (2 preceding siblings ...)
2020-12-07 18:22 ` [ruby-core:101288] " marcandre-ruby-core
@ 2020-12-07 18:58 ` eregontp
2020-12-07 20:19 ` [ruby-core:101291] " marcandre-ruby-core
` (11 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: eregontp @ 2020-12-07 18:58 UTC (permalink / raw
To: ruby-core
Issue #17374 has been updated by Eregon (Benoit Daloze).
Assignee set to shugo (Shugo Maeda)
marcandre (Marc-Andre Lafortune) wrote in #note-3:
> They can be defined in different `refine` blocks and it still works:
Yes, because they are `refine` under the same "refinement namespace" module.
And each `refine` is basically `using` all other `refine` in the same "refinement namespace" module.
The set of refinements that apply are captured at `def` time.
In the original example, there is no way to know that Implementation will be followed by `refine`, and that the methods declared there should be affected.
What you are asking is I think dynamic rebinding, because what should happen if:
```ruby
module R1
refine Foo do
prepend Foo::Implementation
end
end
module R2
refine Foo do
prepend Foo::Implementation
end
end
```
A given (lexical) call site should have a fixed set of used refinements (important for reasoning and performance).
That wouldn't hold for `Foo::Extension::Implementation#foo`, it could be either of R1 or R2 for the same call site.
----------------------------------------
Bug #17374: Refined methods aren't visible from a refinement's module
https://bugs.ruby-lang.org/issues/17374#change-88974
* Author: marcandre (Marc-Andre Lafortune)
* Status: Open
* Priority: Normal
* Assignee: shugo (Shugo Maeda)
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN
----------------------------------------
--
https://bugs.ruby-lang.org/
^ permalink raw reply [flat|nested] 17+ messages in thread
* [ruby-core:101291] [Ruby master Bug#17374] Refined methods aren't visible from a refinement's module
2020-12-07 5:25 [ruby-core:101278] [Ruby master Bug#17374] Refined methods aren't visible from a refinementRefinements that include/prepend module marcandre-ruby-core
` (3 preceding siblings ...)
2020-12-07 18:58 ` [ruby-core:101290] " eregontp
@ 2020-12-07 20:19 ` marcandre-ruby-core
2020-12-07 20:31 ` [ruby-core:101293] " merch-redmine
` (10 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: marcandre-ruby-core @ 2020-12-07 20:19 UTC (permalink / raw
To: ruby-core
Issue #17374 has been updated by marcandre (Marc-Andre Lafortune).
Eregon (Benoit Daloze) wrote in #note-4:
> In the original example, there is no way to know that Implementation will be followed by `refine`, and that the methods declared there should be affected.
>
> What you are asking is I think dynamic rebinding
I might be confused as to what dynamic rebinding is; for me the constraint was that there could not be later redefinitions of refinements, that everything had to had been already defined (which is the case).
When `refine { include Mod }`, I would like the `include` to "duplicate" the *current* methods of `Mod`, just as if I had written them with `def` at that point. Ideally they would be in a different layer than the current refinement, so you could use `prepend`, `def` and `include` on the same method, but at this point that is minor.
Note that I tried `refine { define_method :foo, Mod.instance_method(:foo) }` and that does not work either.
> because what should happen if:
> ```ruby
> module R1
> refine Foo do
> prepend Foo::Implementation
> end
> end
>
> module R2
> refine Foo do
> prepend Foo::Implementation
> end
> end
> ```
More or less the same as if you replaced the `prepend` with the `def`s of `Foo::Implementation` as they were defined at the time.
----------------------------------------
Bug #17374: Refined methods aren't visible from a refinement's module
https://bugs.ruby-lang.org/issues/17374#change-88975
* Author: marcandre (Marc-Andre Lafortune)
* Status: Open
* Priority: Normal
* Assignee: shugo (Shugo Maeda)
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN
----------------------------------------
--
https://bugs.ruby-lang.org/
^ permalink raw reply [flat|nested] 17+ messages in thread
* [ruby-core:101293] [Ruby master Bug#17374] Refined methods aren't visible from a refinement's module
2020-12-07 5:25 [ruby-core:101278] [Ruby master Bug#17374] Refined methods aren't visible from a refinementRefinements that include/prepend module marcandre-ruby-core
` (4 preceding siblings ...)
2020-12-07 20:19 ` [ruby-core:101291] " marcandre-ruby-core
@ 2020-12-07 20:31 ` merch-redmine
2020-12-07 21:06 ` [ruby-core:101294] " marcandre-ruby-core
` (9 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: merch-redmine @ 2020-12-07 20:31 UTC (permalink / raw
To: ruby-core
Issue #17374 has been updated by jeremyevans0 (Jeremy Evans).
I do not think this is a bug. The question to ask yourself is, at the point of call, is the refinement active?. So in method `Implementation#foo`, we are talking about the call to `bar`:
```ruby
def foo
super(bar) # << Can not see bar
end
```
No, the refinement is not active at that point. You can make it active, though doing so is probably not obvious:
```ruby
class Foo
module Extension
module Implementation
end
refine Foo do
prepend Implementation
end
module Implementation
def foo
super(bar) # << Can not see bar
end
def bar # << Bar is in the same module!
42
end
end
end
def foo(value = :none)
p value
end
end
Foo.new
Foo.new.foo # => :none (ok)
# Does not work: undefined local variable or method `bar'
using Foo::Extension
Foo.new.foo rescue (p :error) # => :error
# Works:
Foo.send(:prepend, Foo::Extension::Implementation)
Foo.new.foo # => 42
```
This is because `refine` implicitly activates the refinement, so the refinement is active at the point `bar` is called. This approach works back to Ruby 2.0, with output:
```
:none
:none
42
```
----------------------------------------
Bug #17374: Refined methods aren't visible from a refinement's module
https://bugs.ruby-lang.org/issues/17374#change-88977
* Author: marcandre (Marc-Andre Lafortune)
* Status: Open
* Priority: Normal
* Assignee: shugo (Shugo Maeda)
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN
----------------------------------------
--
https://bugs.ruby-lang.org/
^ permalink raw reply [flat|nested] 17+ messages in thread
* [ruby-core:101294] [Ruby master Bug#17374] Refined methods aren't visible from a refinement's module
2020-12-07 5:25 [ruby-core:101278] [Ruby master Bug#17374] Refined methods aren't visible from a refinementRefinements that include/prepend module marcandre-ruby-core
` (5 preceding siblings ...)
2020-12-07 20:31 ` [ruby-core:101293] " merch-redmine
@ 2020-12-07 21:06 ` marcandre-ruby-core
2020-12-07 21:44 ` [ruby-core:101296] " merch-redmine
` (8 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: marcandre-ruby-core @ 2020-12-07 21:06 UTC (permalink / raw
To: ruby-core
Issue #17374 has been updated by marcandre (Marc-Andre Lafortune).
jeremyevans0 (Jeremy Evans) wrote in #note-6:
> This is because `refine` implicitly activates the refinement, so the refinement is active at the point `bar` is called. This approach works back to Ruby 2.0, with output:
>
> ```
> :none
> :none
> 42
> ```
Thanks for trying it out.
This is not the desired output, though. The last `using` has no effect. Desired output is:
```
:none # No refinement active yet
42 # using was activated
42 # extend works too (assuming the `using` part is commented out...
```
My understanding is that the `refine` simply has no effect, since the module is empty at that point, no?
----------------------------------------
Bug #17374: Refined methods aren't visible from a refinement's module
https://bugs.ruby-lang.org/issues/17374#change-88978
* Author: marcandre (Marc-Andre Lafortune)
* Status: Open
* Priority: Normal
* Assignee: shugo (Shugo Maeda)
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN
----------------------------------------
--
https://bugs.ruby-lang.org/
^ permalink raw reply [flat|nested] 17+ messages in thread
* [ruby-core:101296] [Ruby master Bug#17374] Refined methods aren't visible from a refinement's module
2020-12-07 5:25 [ruby-core:101278] [Ruby master Bug#17374] Refined methods aren't visible from a refinementRefinements that include/prepend module marcandre-ruby-core
` (6 preceding siblings ...)
2020-12-07 21:06 ` [ruby-core:101294] " marcandre-ruby-core
@ 2020-12-07 21:44 ` merch-redmine
2020-12-08 1:05 ` [ruby-core:101300] " shugo
` (7 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: merch-redmine @ 2020-12-07 21:44 UTC (permalink / raw
To: ruby-core
Issue #17374 has been updated by jeremyevans0 (Jeremy Evans).
marcandre (Marc-Andre Lafortune) wrote in #note-7:
> jeremyevans0 (Jeremy Evans) wrote in #note-6:
> > This is because `refine` implicitly activates the refinement, so the refinement is active at the point `bar` is called. This approach works back to Ruby 2.0, with output:
> >
> > ```
> > :none
> > :none
> > 42
> > ```
>
> Thanks for trying it out.
> This is not the desired output, though. The last `using` has no effect. Desired output is:
> ```
> :none # No refinement active yet
> 42 # using was activated
> 42 # extend works too (assuming the `using` part is commented out...
> ```
Ah, thank you for clarifying. I still think the behavior is expected, even if my fix was bad, because the refinement is not active at the point of call. However, only @matz can decide whether this is a bug or expected behavior.
After playing around with it, I found a way to get it to work without duplicating the literal method definitions. It's not much better than calling `class_eval` with the same string in two places, though:
```ruby
class Foo
module Extension
RefinedImplementation = refine Foo do
def foo(value=:none)
super(bar) # << Can not see bar
end
def bar # << Bar is in the same module!
42
end
end
module Implementation
RefinedImplementation.public_instance_methods(false).each do |m|
define_method(m, RefinedImplementation.instance_method(m))
end
end
end
def foo(value = :none)
p value
end
end
```
I'd probably use `class_eval` with the same string instead of this.
----------------------------------------
Bug #17374: Refined methods aren't visible from a refinement's module
https://bugs.ruby-lang.org/issues/17374#change-88980
* Author: marcandre (Marc-Andre Lafortune)
* Status: Open
* Priority: Normal
* Assignee: shugo (Shugo Maeda)
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN
----------------------------------------
--
https://bugs.ruby-lang.org/
^ permalink raw reply [flat|nested] 17+ messages in thread
* [ruby-core:101300] [Ruby master Bug#17374] Refined methods aren't visible from a refinement's module
2020-12-07 5:25 [ruby-core:101278] [Ruby master Bug#17374] Refined methods aren't visible from a refinementRefinements that include/prepend module marcandre-ruby-core
` (7 preceding siblings ...)
2020-12-07 21:44 ` [ruby-core:101296] " merch-redmine
@ 2020-12-08 1:05 ` shugo
2020-12-08 4:01 ` [ruby-core:101303] " marcandre-ruby-core
` (6 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: shugo @ 2020-12-08 1:05 UTC (permalink / raw
To: ruby-core
Issue #17374 has been updated by shugo (Shugo Maeda).
It's intended behavior.
Refinements are activated either in scope where using is called or in blocks given to refine.
I don't recommend module inclusion to define refined methods.
----------------------------------------
Bug #17374: Refined methods aren't visible from a refinement's module
https://bugs.ruby-lang.org/issues/17374#change-88986
* Author: marcandre (Marc-Andre Lafortune)
* Status: Open
* Priority: Normal
* Assignee: shugo (Shugo Maeda)
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN
----------------------------------------
--
https://bugs.ruby-lang.org/
^ permalink raw reply [flat|nested] 17+ messages in thread
* [ruby-core:101303] [Ruby master Bug#17374] Refined methods aren't visible from a refinement's module
2020-12-07 5:25 [ruby-core:101278] [Ruby master Bug#17374] Refined methods aren't visible from a refinementRefinements that include/prepend module marcandre-ruby-core
` (8 preceding siblings ...)
2020-12-08 1:05 ` [ruby-core:101300] " shugo
@ 2020-12-08 4:01 ` marcandre-ruby-core
2020-12-08 4:04 ` [ruby-core:101304] " marcandre-ruby-core
` (5 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: marcandre-ruby-core @ 2020-12-08 4:01 UTC (permalink / raw
To: ruby-core
Issue #17374 has been updated by marcandre (Marc-Andre Lafortune).
jeremyevans0 (Jeremy Evans) wrote in #note-8:
> After playing around with it, I found a way to get it to work without duplicating the literal method definitions.
Ah! I had tried the other way (doesn't work), but from refinement module to the module it works, thanks for figuring this out 👍
> It's not much better than calling `class_eval` with the same string in two places
I think it is. A string isn't parsable (e.g. RuboCop, AST-based search tools, ...), nor syntax-highlightable, nor as debuggable, won't be detected by help generation tools, etc...
This way I can write what I wanted:
```
class Foo
module Extension
import refine(Foo) {
def foo
super(bar) # << Can not see bar
end
def bar # << Bar is in the same module!
42
end
}
end
def foo(value = :none)
p value
end
end
# Does not work: undefined local variable or method `bar'
if ENV['USING']
using Foo::Extension
else
Foo.prepend Foo::Extension
end
Foo.new.foo rescue (p :error) # => 42, works both ways
```
With this refinement active...
```ruby
refine Module do
def import(refined_mod)
refined_mod.instance_methods(false).each do |m|
define_method(m, refined_mod.instance_method(m))
end
end
end
```
----------------------------------------
Bug #17374: Refined methods aren't visible from a refinement's module
https://bugs.ruby-lang.org/issues/17374#change-88991
* Author: marcandre (Marc-Andre Lafortune)
* Status: Open
* Priority: Normal
* Assignee: shugo (Shugo Maeda)
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN
----------------------------------------
--
https://bugs.ruby-lang.org/
^ permalink raw reply [flat|nested] 17+ messages in thread
* [ruby-core:101304] [Ruby master Bug#17374] Refined methods aren't visible from a refinement's module
2020-12-07 5:25 [ruby-core:101278] [Ruby master Bug#17374] Refined methods aren't visible from a refinementRefinements that include/prepend module marcandre-ruby-core
` (9 preceding siblings ...)
2020-12-08 4:01 ` [ruby-core:101303] " marcandre-ruby-core
@ 2020-12-08 4:04 ` marcandre-ruby-core
2020-12-08 4:39 ` [ruby-core:101305] " merch-redmine
` (4 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: marcandre-ruby-core @ 2020-12-08 4:04 UTC (permalink / raw
To: ruby-core
Issue #17374 has been updated by marcandre (Marc-Andre Lafortune).
shugo (Shugo Maeda) wrote in #note-9:
> I don't recommend module inclusion to define refined methods.
Indeed!
The question remains: if it's a bad idea to `include/prepend` modules inside a `refine` block, could we not make it a good idea? Would it be technically difficult to duplicate the methods in the included module, import them and active them in the refinement?
----------------------------------------
Bug #17374: Refined methods aren't visible from a refinement's module
https://bugs.ruby-lang.org/issues/17374#change-88992
* Author: marcandre (Marc-Andre Lafortune)
* Status: Open
* Priority: Normal
* Assignee: shugo (Shugo Maeda)
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN
----------------------------------------
--
https://bugs.ruby-lang.org/
^ permalink raw reply [flat|nested] 17+ messages in thread
* [ruby-core:101305] [Ruby master Bug#17374] Refined methods aren't visible from a refinement's module
2020-12-07 5:25 [ruby-core:101278] [Ruby master Bug#17374] Refined methods aren't visible from a refinementRefinements that include/prepend module marcandre-ruby-core
` (10 preceding siblings ...)
2020-12-08 4:04 ` [ruby-core:101304] " marcandre-ruby-core
@ 2020-12-08 4:39 ` merch-redmine
2020-12-08 20:37 ` [ruby-core:101323] " eregontp
` (3 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: merch-redmine @ 2020-12-08 4:39 UTC (permalink / raw
To: ruby-core
Issue #17374 has been updated by jeremyevans0 (Jeremy Evans).
marcandre (Marc-Andre Lafortune) wrote in #note-10:
> jeremyevans0 (Jeremy Evans) wrote in #note-8:
> > It's not much better than calling `class_eval` with the same string in two places
>
> I think it is. A string isn't parsable (e.g. RuboCop, AST-based search tools, ...), nor syntax-highlightable, nor as debuggable, won't be detected by help generation tools, etc...
As commonly used, you are correct. However, one possibility is:
```ruby
path = File.expand_path('implementation.rb', __dir__)
code = File.read(path)
refine(Foo){class_eval(code, path)}
Implementation = Module.new{class_eval(code, path)}
```
This should be parsable and syntax-highlightable at least. I'm less sure about debuggability and interaction with help generation tools, though. Loss of code locality is definitely a downside.
----------------------------------------
Bug #17374: Refined methods aren't visible from a refinement's module
https://bugs.ruby-lang.org/issues/17374#change-88993
* Author: marcandre (Marc-Andre Lafortune)
* Status: Open
* Priority: Normal
* Assignee: shugo (Shugo Maeda)
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN
----------------------------------------
--
https://bugs.ruby-lang.org/
^ permalink raw reply [flat|nested] 17+ messages in thread
* [ruby-core:101323] [Ruby master Bug#17374] Refined methods aren't visible from a refinement's module
2020-12-07 5:25 [ruby-core:101278] [Ruby master Bug#17374] Refined methods aren't visible from a refinementRefinements that include/prepend module marcandre-ruby-core
` (11 preceding siblings ...)
2020-12-08 4:39 ` [ruby-core:101305] " merch-redmine
@ 2020-12-08 20:37 ` eregontp
2020-12-09 1:33 ` [ruby-core:101324] " shugo
` (2 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: eregontp @ 2020-12-08 20:37 UTC (permalink / raw
To: ruby-core
Issue #17374 has been updated by Eregon (Benoit Daloze).
Status changed from Open to Rejected
marcandre (Marc-Andre Lafortune) wrote in #note-11:
> The question remains: if it's a bad idea to `include/prepend` modules inside a `refine` block, could we not make it a good idea? Would it be technically difficult to duplicate the methods in the included module, import them and active them in the refinement?
That actually means duplicating the inline caches and so probably also the bytecode, etc.
So it doesn't seem a good idea at least from a memory footprint point of view.
Given shugo is AFAIK responsible for the refinements specification and he confirmed it's intended behavior, I'll close this issue (but feel free to continue the discussion).
----------------------------------------
Bug #17374: Refined methods aren't visible from a refinement's module
https://bugs.ruby-lang.org/issues/17374#change-89017
* Author: marcandre (Marc-Andre Lafortune)
* Status: Rejected
* Priority: Normal
* Assignee: shugo (Shugo Maeda)
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN
----------------------------------------
--
https://bugs.ruby-lang.org/
^ permalink raw reply [flat|nested] 17+ messages in thread
* [ruby-core:101324] [Ruby master Bug#17374] Refined methods aren't visible from a refinement's module
2020-12-07 5:25 [ruby-core:101278] [Ruby master Bug#17374] Refined methods aren't visible from a refinementRefinements that include/prepend module marcandre-ruby-core
` (12 preceding siblings ...)
2020-12-08 20:37 ` [ruby-core:101323] " eregontp
@ 2020-12-09 1:33 ` shugo
2020-12-10 15:03 ` [ruby-core:101395] " daniel
2020-12-10 17:36 ` [ruby-core:101401] " marcandre-ruby-core
15 siblings, 0 replies; 17+ messages in thread
From: shugo @ 2020-12-09 1:33 UTC (permalink / raw
To: ruby-core
Issue #17374 has been updated by shugo (Shugo Maeda).
marcandre (Marc-Andre Lafortune) wrote in #note-11:
> shugo (Shugo Maeda) wrote in #note-9:
> > I don't recommend module inclusion to define refined methods.
>
> Indeed!
>
> The question remains: if it's a bad idea to `include/prepend` modules inside a `refine` block, could we not make it a good idea? Would it be technically difficult to duplicate the methods in the included module, import them and active them in the refinement?
In addition to implementation issues described by eregon, it may be confusing because it changes the semantics of include/prepend to code duplication like Module#mix proposed by Matz before.
Anyway, your proposal should be filed as a feature ticket.
----------------------------------------
Bug #17374: Refined methods aren't visible from a refinement's module
https://bugs.ruby-lang.org/issues/17374#change-89022
* Author: marcandre (Marc-Andre Lafortune)
* Status: Rejected
* Priority: Normal
* Assignee: shugo (Shugo Maeda)
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN
----------------------------------------
--
https://bugs.ruby-lang.org/
^ permalink raw reply [flat|nested] 17+ messages in thread
* [ruby-core:101395] [Ruby master Bug#17374] Refined methods aren't visible from a refinement's module
2020-12-07 5:25 [ruby-core:101278] [Ruby master Bug#17374] Refined methods aren't visible from a refinementRefinements that include/prepend module marcandre-ruby-core
` (13 preceding siblings ...)
2020-12-09 1:33 ` [ruby-core:101324] " shugo
@ 2020-12-10 15:03 ` daniel
2020-12-10 17:36 ` [ruby-core:101401] " marcandre-ruby-core
15 siblings, 0 replies; 17+ messages in thread
From: daniel @ 2020-12-10 15:03 UTC (permalink / raw
To: ruby-core
Issue #17374 has been updated by Dan0042 (Daniel DeLorme).
I tried testing this and immediately ran into this issue: (in latest master)
```ruby
class Foo
module Extension
module Implementation
def foo
super(bar)
end
def bar
42
end
end
refine Foo do
prepend Implementation
end
end
def foo(value = :none)
p value
end
end
Foo.new.foo # => :none (ok)
Foo.prepend Foo::Extension::Implementation
Foo.new.foo # => :none ... not 42 as expected
```
So it appears like `Foo.prepend Foo::Extension::Implementation` has no effect. But if I just comment out the `prepend Implementation` line it works as expected. Note that there's no `using` anywhere anyway. I'm at a loss to explain what's going on here. But I think more than ever that module inclusion to define refined methods is not just "not recommended", it should be prevented by raising an error. Or at least output a warning.
----------------------------------------
Bug #17374: Refined methods aren't visible from a refinement's module
https://bugs.ruby-lang.org/issues/17374#change-89155
* Author: marcandre (Marc-Andre Lafortune)
* Status: Rejected
* Priority: Normal
* Assignee: shugo (Shugo Maeda)
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN
----------------------------------------
--
https://bugs.ruby-lang.org/
^ permalink raw reply [flat|nested] 17+ messages in thread
* [ruby-core:101401] [Ruby master Bug#17374] Refined methods aren't visible from a refinement's module
2020-12-07 5:25 [ruby-core:101278] [Ruby master Bug#17374] Refined methods aren't visible from a refinementRefinements that include/prepend module marcandre-ruby-core
` (14 preceding siblings ...)
2020-12-10 15:03 ` [ruby-core:101395] " daniel
@ 2020-12-10 17:36 ` marcandre-ruby-core
15 siblings, 0 replies; 17+ messages in thread
From: marcandre-ruby-core @ 2020-12-10 17:36 UTC (permalink / raw
To: ruby-core
Issue #17374 has been updated by marcandre (Marc-Andre Lafortune).
Yup, that's a bug, good catch.
I believe is the same as #17379 because if you comment the first `Foo.new.foo` then it works as expected. I added a simplified version to that issue
----------------------------------------
Bug #17374: Refined methods aren't visible from a refinement's module
https://bugs.ruby-lang.org/issues/17374#change-89161
* Author: marcandre (Marc-Andre Lafortune)
* Status: Rejected
* Priority: Normal
* Assignee: shugo (Shugo Maeda)
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN
----------------------------------------
--
https://bugs.ruby-lang.org/
^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2020-12-10 17:36 UTC | newest]
Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-12-07 5:25 [ruby-core:101278] [Ruby master Bug#17374] Refined methods aren't visible from a refinementRefinements that include/prepend module marcandre-ruby-core
2020-12-07 5:26 ` [ruby-core:101279] [Ruby master Bug#17374] Refined methods aren't visible from a refinement's module marcandre-ruby-core
2020-12-07 10:25 ` [ruby-core:101283] " eregontp
2020-12-07 18:22 ` [ruby-core:101288] " marcandre-ruby-core
2020-12-07 18:58 ` [ruby-core:101290] " eregontp
2020-12-07 20:19 ` [ruby-core:101291] " marcandre-ruby-core
2020-12-07 20:31 ` [ruby-core:101293] " merch-redmine
2020-12-07 21:06 ` [ruby-core:101294] " marcandre-ruby-core
2020-12-07 21:44 ` [ruby-core:101296] " merch-redmine
2020-12-08 1:05 ` [ruby-core:101300] " shugo
2020-12-08 4:01 ` [ruby-core:101303] " marcandre-ruby-core
2020-12-08 4:04 ` [ruby-core:101304] " marcandre-ruby-core
2020-12-08 4:39 ` [ruby-core:101305] " merch-redmine
2020-12-08 20:37 ` [ruby-core:101323] " eregontp
2020-12-09 1:33 ` [ruby-core:101324] " shugo
2020-12-10 15:03 ` [ruby-core:101395] " daniel
2020-12-10 17:36 ` [ruby-core:101401] " marcandre-ruby-core
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).