Перенаправление / делегирование 2 аргументов в ruby

class MyClass
  extend Forwardable
  def_delegators :@broker, :add

  def subscribe_in_broker
    @subscribers.map(&method(:add))
  end
end

В этом примере @subscribers - это Hash, а @broker.add принимает два аргумента: def broker(k,v).

Это вызывает ArgumentError: wrong number of arguments (given 1, expected 2)

Есть ли способ использовать Forwardable или подобное решение без этой проблемы? Как я могу легко делегировать массив с двумя элементами методу, который принимает два аргумента? Что было бы эквивалентно написанию:

  def subscribe_in_broker
    @subscribers.map{|k,v| add(k,v) }
  end

но используя делегирование?

Пошаговое руководство по созданию собственного Slackbot: От установки до развертывания
Пошаговое руководство по созданию собственного Slackbot: От установки до развертывания
Шаг 1: Создание приложения Slack Чтобы создать Slackbot, вам необходимо создать приложение Slack. Войдите в свою учетную запись Slack и перейдите на...
1
0
259
1

Ответы 1

Может показаться, что блок получает 2 аргумента, но на самом деле он получает только один аргумент (массив из 2 элементов). Ruby интерпретирует |x, y|, как если бы это был |(x, y)|. Скобки (которые здесь можно опустить) разрушать единственный аргумент на две части.

Когда вы используете & с методом, он также получает только 1 аргумент, и если вы хотите его деструктурировать, вы должны быть явно, используя набор круглых скобок вокруг x и y:

def add((x,y))
end

Чтобы было ясно, это метод с одним аргументом, который ожидает, что аргумент будет массивом. Например, вы называете это так: add([1, 2])

Примечание: здесь ничего такого связано с делегированием, просто потому, что Ruby предполагает, что вы собираетесь деструктурировать в одном месте, а не в другом.

Можно передать более одного аргумента блоку (или метод, превращенный в процедуру с помощью '&'), но это не то, что делает map.

Для меня не очевидно, почему hash.map { |x,y| add(x, y) } не подходит для ваших целей. Чтобы обойти это, вам нужно будет определить свою собственную функцию map, которая дает 2 аргумента вместо 1, и это кажется излишним для этого.

Спасибо за полезный ответ. Мой был мусором (и я удалил его, чтобы не вводить себя в заблуждение и других).

Lemon Cat 20.03.2018 22:11

Другие вопросы по теме