Feature #9552

Module map!

Added by Boris Stitnicky about 1 year ago. Updated 12 months ago.

[ruby-core:60986]
Status:Feedback
Priority:Normal
Assignee:-

Description

I would like to beg for map! directive in Module. I can imitate it with this code:

class Module
  def map! **hash, &block
    hash.each_pair { |mapped_method_symbol, original_method_symbol|
      define_method mapped_method_symbol do |*args, &b|
        block.( send original_method_symbol, *args, &b )
      end
    }
  end
end

And then

class Foo; attr_accessor :name end
class Bar; attr_accessor :name end
class Baz; attr_accessor :name end

class FooBarBazCollection < Array
  def foos; select { |e| e.is_a? Place } end
  def bars; select { |e| e.is_a? Transition } end
  def bazs; select { |e| e.is_a? Arc } end
  map! fn: :foos, barn: :bars, bazn: :bazs do |retval| retval.map &:name end
end

I solemnly declare that I have encountered this pattern in my work on Petri net gem sufficiently many times to warrant this meta approach. The above method #map! is not perfect, because it makes the "mapped" methods more omnivorous -- accepting even such sets of arguments, for which the originals returned ArgumentError. I do not know how to solve this without asking for a core-level solution.

History

#1 Updated by Boris Stitnicky about 1 year ago

Core-level syntax might be similar to that of alias,

class FooBarBazCollection
  map! fn foos, barn bar, bazn bazs do |retval| retval.map &:name end
end

Another approach (without introducing a new keyword, which might be considered feature creep) would be to somehow make it possible for the built-in argument field validation of one method to be applied to another method. But that would probably require more introspection regarding the argument field than present day #arity method offers, and also the possibility to unbind the argument field validation routine from a method and reuse it in another method. Then, perfect Module#map! could be written and there would be no pressing need for new keywords.

I have created a new thread for this, #9553.

#2 Updated by Boris Stitnicky about 1 year ago

I failed to notice that Method#parameters was already available. This makes it possible for me to implement my desired Module#map! and other metaprogramming without asking for novel core syntax. The reasons supporting this feature suggestion are thus much weaker than I thougt.

#3 Updated by Yukihiro Matsumoto about 1 year ago

  • Status changed from Open to Feedback

I am not sure I understand your intention fully, but at least map! reminds us too much of enumerators.
I don't think there's a chance to add map! to module. Try another name.

Maybe some kind of method (or function) combination natation can help you.

Matz.

#4 Updated by Boris Stitnicky 12 months ago

I apologize for late response. Again, I experienced that the method I'm proposing here has much practical use in my code. As for better name, I can think of:

#compose --- weight: 3 -- as in functional composition
#apply --- weight: 1 -- as in functional application
#chain --- weight: 4 -- as in method chaining

#compose is perhaps the most politically correct. While #apply is not theoretically incorrect, the word too generic (much like using) and overloads the metalanguage (English speaking about Ruby) too much. From these newly made up options, I personally prefer #chain, which is sufficiently rare, expressive, and short to boot. I will be renaming Module#map! to Module#chain in my personal library, too -- thank you for forcing me to think.

Also available in: Atom PDF