Ruby将任意函数和参数传递给另一个函数

时间:2018-10-24 16:23:45

标签: ruby

我正在尝试学习Ruby。我想将任意函数以及参数和关键字参数的任意列表传递给另一个函数。

例如,我下面有这个任意函数

def dummy_func(a, b)
   return a+b
end

我有这个包装器功能

def wrapper(func, *args, **kwargs)
    func(args, kwargs))
end

我想要它,因此我可以通过以下任何一种方式传递参数,并且仍然返回正确的答案

wrapper(dummy_func, a=1, b=2)
wrapper(dummy_func, 1, b=2)
wrapper(dummy_func, a=1, b=2)
wrapper(dummy_func, 1, 2)

在Ruby中有可能吗?惯用的处理方式是什么?

2 个答案:

答案 0 :(得分:1)

惯用的方法是改为yield to a block

def dummy_func(a, b, key:)
   return a+b+key
end

def wrapper
  puts yield
end

a = 4
b = 5
c = 6
wrapper do
  dummy_func(a ,b, key: c)
end

由于块是闭合的,因此可以看到与调用wrapper相同的所有变量。现在,无需传递包装程序的参数。


如果您真的想包装,可以进行some introspection to determine what arguments the wrapped function takes

def dummy_func(a, b=23, key: 42)
   return a+b+key
end

def no_keys(a, b=23)
   return a+b
end

def wrapper(func, *array, **hash)
  method = self.method(func)
  takes_array = method.parameters.any? { |p| [:req,:opt].include?(p[0]) }
  takes_hash = method.parameters.any? { |p| [:keyreq,:key].include?(p[0]) }

  if takes_array && takes_hash
    self.send(func, *array, **hash)
  elsif takes_array
    self.send(func, *array)
  elsif takes_hash
    self.send(func, **hash)
  else
    self.send(func)
  end
end

a = 4
b = 5
c = 6
puts wrapper(:dummy_func, a, b, key:c)
puts wrapper(:no_keys, a, b)

但是,这比屈服于一个块要复杂得多,灵活性也要差一些。这也将您限制为实际上是methods on the main object的“函数”(Ruby中没有函数引用)。这就是为什么用self.send来调用它们的原因。块不需要假设要包装的内容。

答案 1 :(得分:0)

最接近的是关键字参数:

https://www.justinweiss.com/articles/fun-with-keyword-arguments/

def hello_message(greeting, time_of_day, first_name:, last_name:)
  "#{greeting} #{time_of_day}, #{first_name} #{last_name}!"
end

args = ["Morning"]
keyword_args = {last_name: "Weiss"}

hello_message("Good", *args, first_name: "Justin", **keyword_args)
=> "Good Morning, Justin Weiss!"