Project

General

Profile

Actions

Feature #17380

closed

Useful `include/prepend` in `refine`

Added by marcandre (Marc-Andre Lafortune) over 3 years ago. Updated over 2 years ago.

Status:
Closed
Target version:
-
[ruby-core:101326]

Description

Currently, prepend/include within a refine block leads to a method not being to see itself, or others defined in the same module:

module Code
  def recurse(value = nil)
    return value if value

    recurse(42) # => NoMethodError!!!
  end
end

module Extension
  refine Object do
    include Code
  end
end

using Extension
:x.recurse(:y) # => :y (ok)
:x.recurse     # => NoMethodError, was hoping for 42

I find this unintuitive and not useful.

The conclusion of the current situation from @shugo (Shugo Maeda) and others is "I don't recommend module inclusion to define refined methods"

Could we change this situation so it can be recommended to use it?

What I believe would be more useful and is what I expected was that include/prepend within a Module would bring in the current methods in the Module, with the current refinements activated.

One use-case in particular is to publish libraries where one can give the option to the user to either:

  • call using GreatExtension in each and every file that need it
  • or MyClass.prepend GreatExtension once.

While Jeremy Evans found a way to do it, it remains challenging and unnatural.


Related issues 1 (0 open1 closed)

Related to Ruby master - Bug #17374: Refined methods aren't visible from a refinement's moduleRejectedshugo (Shugo Maeda)Actions
Actions #1

Updated by Eregon (Benoit Daloze) over 3 years ago

  • Related to Bug #17374: Refined methods aren't visible from a refinement's module added

Updated by Eregon (Benoit Daloze) over 3 years ago

Maybe we should allow include RefinedImplementation from https://bugs.ruby-lang.org/issues/17374#note-8 ?
Copying methods manually seems to have a very similar effect, but it would be more convenient.

Updated by Dan0042 (Daniel DeLorme) over 3 years ago

It would be nice if prepend/include worked within a refine block, but if they don't then at least it should raise an error. In that respect I disagree with closing #17374; even if the result is "expected", the fact that including a module is effectively a no-op should be considered a bug. Silently failing to have an effect is not so good.

Updated by marcandre (Marc-Andre Lafortune) over 3 years ago

Dan0042 (Daniel DeLorme) wrote in #note-3:

including a module is effectively a no-op

It isn't a no-op, as it does bring each method in the refinement, but those methods "live" outside of said refinement. See my example above where :x.recurse(:y) # => :y (ok).

Updated by Dan0042 (Daniel DeLorme) over 3 years ago

marcandre (Marc-Andre Lafortune) wrote in #note-4:

It isn't a no-op, as it does bring each method in the refinement, but those methods "live" outside of said refinement. See my example above where :x.recurse(:y) # => :y (ok).

Yes, I understand that, but even if the methods are technically in the refinement, if they are unreachable then effectively it's the same as a no-op. Although as the example shows it's more like a "half-op"; the methods are reachable from the outside but not the inside.

Actions #6

Updated by jeremyevans0 (Jeremy Evans) over 2 years ago

  • Status changed from Open to Closed
Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0