我正在尝试学习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中有可能吗?惯用的处理方式是什么?
答案 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!"