Search code examples
rubymetaprogrammingblock

How to allow multiple parameters to be passed into define_singleton_method


I want to create a class that can add methods dynamically and allow multiple parameters.

For example:

r = Robot.new
r.learn_maneuvering('turn') { |degree| puts "turning #{degree} degrees" }
r.turn 50 # => turning 50 degrees
r.turn 50, 60 # => turning 50 degrees # => turning 60 degrees

My first attempt was this:

def learn_maneuvering(name, &block)
    define_singleton_method(name, &block) 
end

However, it only accounts for one parameter..

I then started with:

def learn_maneuvering(name, &block)
    define_singleton_method(name) do |*args|
        # to do
    end
end

I believe this will loop until all arguments are used right? Anywho, I am not sure how to pass these arguments to the given block.


Solution

  • You're close:

    def learn_maneuvering(name, &block)
      define_singleton_method(name) do |*args|
        args.each do |arg|
          block.call(arg)
        end
      end
    end
    
    r = Robot.new
    r.learn_maneuvering('turn') { |degree| puts "turning #{degree} degrees" }
    
    r.turn 50, 60
    

    prints:

    turning 50 degrees
    turning 60 degrees

    But is this really what you want? It seems like just doing

    r.turn 50
    r.turn 60
    

    makes more sense to me.