Define method parameters for meta programming in Ruby

不打扰是莪最后的温柔 提交于 2019-12-23 22:36:28

问题


In Ruby, we can define instance methods with meta-programming like:

define_method(:hi) { 'Hello, SO world!' } # => :hi
hi                                        # => "Hello, SO world!"

This way, it is possible to define a method with a dynamic name:

dynamic_name = :hi                                 # => :hi
define_method(dynamic_name) { 'Hello, SO world!' } # => :hi
hi                                                 # => "Hello, SO world!"

We can also inject arguments in to a dynamic method:

dynamic_name = :hi # => :hi
define_method(dynamic_name) do |arg1, arg2, &block|
  'Hello, SO world!'
end                # => :hi
hi(42, 42) { 42 }  # => "Hello, SO world!"

So far, so good.

But how could we do to inject dynamic arguments? Would it be possible to replace arg1, arg2, &block by a dynamic notation?

Thanks for any tips, best practices, or even ideas.

Edit:

In other words, I would like to dynamically also define the parameters and the block of an instance method.

However, I would like to do so with a particular number of parameters (which could be 0), an array in option, and to finish the block of the method.

This way, I could avoid having methods such as:

dynamic_name = :hi      # => :hi
define_method(dynamic_name) do |*args, &block|
  'f'
end                     # => :hi
hi                      # => "f"
hi(:foo)                # => "f"
hi(:foo, :fooo)         # => "f"
hi(:foo, :fooo, :foooo) # => "f"

...which is a nonsense, because here we can give to the method an infinite number of unused parameters. I would like to avoid this situation.

Edit 2:

The reason is the following:

In Ruby, when we need a method which do not need any parameters, we can simply do:

def my_method
  "Hello, SO world!"
end

However, if instead I do this:

def my_method(*args)
  "Hello, SO world!"
end

...the result is still the same, but because the parameter (the array args) is useless, it would be better to keep it simple by removing it from the method.


回答1:


Try passing an array or dictionary.

UPDATE:

if condition1
  class_eval <<-EVAL
    def #{"my_method"}(arg1)
    end
  EVAL
else  
    class_eval <<-EVAL
      def #{"my_method"}
      end
  EVAL
end

UPDATE2:

if condition1
  self.instance_eval <<-EVAL
    def #{"my_method"}(arg1)
    end
  EVAL
else  
    self.instance_eval <<-EVAL
      def #{"my_method"}
      end
  EVAL
end

UPDATE3:

# or
self.instance_eval("def method1(arg1) puts 'hellowa' + arg1.to_s; end")
self.instance_eval("def method2() puts 'hellowa2'; end")

# and then
method1(33) # => hellowa33
method2 # => hellowa2


来源:https://stackoverflow.com/questions/33425935/define-method-parameters-for-meta-programming-in-ruby

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!