🙌

[Feature #21813] ...引数のメタ情報を Method#parameters で取得できるようにする提案

に公開

[Feature #21813] Add [:forward, :...] symbol tuple to indicate forwarding arguments when calling Method#parameters

  • * ** & 引数の場合に Method#parameters で引数のシグネチャを取得しようとすると以下のように * ** & の情報をそのまま取得できる
def foo(*, **, &)
end

pp method(:foo).parameters
# => [[:rest, :*], [:keyrest, :**], [:block, :&]]
  • なのでこの情報を利用して以下のように動的にメソッドの引数を参照する事ができる
def foo(*, **, &)
  method(__method__).parameters => [*, [:rest, rest], *]
  p rest # => :*

  # print(*) と同等
  binding.eval "print(#{rest})" # => 123
end

foo(1, 2, 3)
  • 一方で ... 引数の場合は ... ではなくて * ** & の情報が返ってくる
def foo(...)
end

pp method(:foo).parameters
# => [[:rest, :*], [:keyrest, :**], [:block, :&]]
  • なので先程書いたような動的にメソッドの引数を参照するとエラーになってしまう
def foo(...)
  # `...` という記号で受け取る事ができない
  method(__method__).parameters => [*, [:rest, rest], *]
  p rest # => :*

  # print(*) と呼び出そうとするが引数のシグネチャが異なるのでエラーになる
  binding.eval "print(#{rest})" # => 123
  # error: unexpected `*`; no anonymous rest parameter
end

foo(1, 2, 3)
  • これに対応するために ... 引数の場合は Method#parameters の戻り値を [:forward, :...] にする提案
  • メタプロする場合はこういうのがボトルネックになるので普通にほしいなあ
GitHubで編集を提案

Discussion