Ruby, передающий произвольную функцию и параметры в другую функцию - PullRequest
0 голосов
/ 24 октября 2018

Я пытаюсь выучить 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 голосов
/ 24 октября 2018

Идиоматический способ состоит в том, чтобы вместо уступить блоку .

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.Блоки не требуют никаких предположений о том, что упаковывается.

0 голосов
/ 24 октября 2018

Ближайшие аргументы для ключевых слов:

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!"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...