Идиоматический способ состоит в том, чтобы вместо уступить блоку .
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
.Теперь нет необходимости передавать аргументы обертки.
Если вы действительно хотите сделать обертку, вы можете сделать некоторый самоанализ, чтобы определить, какие аргументы обернутая функция принимает .
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)
Но это немного сложнее и менее гибко, чем уступать блоку.Это также ограничивает вас «функциями», которые на самом деле являются методами основного объекта (в Ruby нет ссылок на функции).Вот почему они звонят с self.send
.Блоки не требуют никаких предположений о том, что упаковывается.