(*) シグネチャを持つ Ruby メソッド
概要
パターン マッチングに関するこの興味深いブログ投稿には、(*) のメソッド シグネチャを持つコードがいくつかあります。
class Request < Data.define(:path, :scheme, :format)
def deconstruct_keys(*)
{ path: @path, scheme: @scheme, format: @format }
end
def deconstruct(*)
path.split("/").compact
end
end
これは違う
def a_method(*args)
Ruby のドキュメントには情報が見つかりませんでした。
def deconstruct_keys(*) とはどういう意味ですか?
注: この質問は Ruby Weekly で言及されました。
解決策
def a_method(*args)
...
end
通常、これを記述すると、args 変数に格納されているメソッドのすべての引数のリストが取得されます。
def a_method(*)
...
end
これは同じ匿名形式です。任意の数の引数を受け入れますが、そのリスト変数に名前を付けたくありません。ここでは引数のリストに名前を付けていませんが、それを別の引数リストに分割することはできます。したがって、これは合法ではありませんが、
def a_method(*)
# Should've just named it in the first place :(
args = *
...
end
一方、これは
def a_method(*)
another_method(*)
end
そして引数をanother_methodに渡します。それは以下と同等です
def a_method(*args)
another_method(*args)
end
Ruby 3 のキーワード引数でも同じことができます
def a_method(**)
another_method(**)
end
すべての引数を転送することが目的の場合は、省略記号構文を使用する必要があることに注意してください。
def a_method(...)
another_method(...)
end
単独の * は、キーワード引数を委任するときにおかしな動作をします。例えば、
def foo(*args, **kwargs)
p args
p kwargs
end
def bar(*)
foo(*)
end
foo(1, a: 1) # Prints [1] then {:a=>1}
bar(1, a: 1) # Prints [1, {:a=>1}], then {}
foo を直接呼び出す場合、名前付き引数の構文は **kwargs に渡されますが、bar を介して委任する場合は、ハッシュに変換されてから args に渡されます。その上、 はブロック引数も転送しませんが、 … は「位置引数、名前付き引数、およびブロック引数をすべて転送する」という汎用のキャッチオールです。