Как определить, как Ruby аргументы метода будут связаны без вызова метода - PullRequest
1 голос
/ 07 января 2020

Поскольку в Ruby есть несколько различных типов параметров метода (обязательно, по умолчанию, ключевое слово, переменная длина ...), иногда определить, как фактические аргументы будут связаны с формальными параметрами, может быть непросто.

Мне интересно, есть ли способ определить, какой будет эта привязка без фактического вызова метода. Например, для следующего метода A#foo:

class A
   def foo(a, *b, c)
      ...
   end
end

я хотел бы использовать метод, подобный determine_binding, который мы можем использовать следующим образом:

A.instance_method(:foo).determine_binding(1,2,3,4,5) ## returns { a: 1, b: [2,3,4], c: 5 }

То есть determine_binding принимает список аргументов и определяет формальную привязку к параметрам foo, фактически не вызывая foo. Есть ли что-то подобное (или подобное) в Ruby?

Ответы [ 2 ]

3 голосов
/ 07 января 2020

Вы можете go с крошечным DSL для этой цели.

module Watcher
  def self.prepended(base)
    base.instance_methods(false).map do |m|
      mthd = base.instance_method(m)
      names = mthd.parameters.map(&:last).map(&:to_s)
      values = names.join(", ")
      params =
        mthd.parameters.map do |type, name|
          case type
          when :req then name.to_s
          when :rest then "*#{name}"
          when :keyrest then "**#{name}"
          when :block then "&#{name}"
          end
        end.join(", ")
      base.class_eval """
        def #{m}(#{params})
          #{names}.zip([#{values}]).to_h
        end
      """
    end
  end
end

class A; def zoo(a, *b, c); 42; end; end
A.new.zoo(1,2,3,4,5)
#⇒ 42

A.prepend Watcher
A.new.zoo(1,2,3,4,5)
#⇒ {"a"=>1, "b"=>[2, 3, 4], "c"=>5}
2 голосов
/ 07 января 2020

Так близко. Вы ищете Method#parameters

A.instance_method(:foo).parameters => [[:req, :a], [:rest, :b], [:req, :c]]

Для получения дополнительной информации см. Документацию " Метод ".

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...