配列はオブジェクトの前に*
を、ハッシュはオブジェクトの前に**
を付けることで「展開」することができます。「展開」が何を意味しているかは、マージや引数の欄を参照してイメージを掴んでください。
マージ
merge
メソッドやreverse_merge
メソッドを使ってもハッシュをマージできますが、**
で展開すると簡潔に書けます。
pp ([1, *[2, 3]])
# => [1, 2, 3]
pp ({ hoge: 1, **{ fuga: 2 } })
# => { hoge: 1, fuga: 2 }
ハッシュのキーが重複している場合は、後に指定した値が優先されます。ただし、展開したハッシュの値が展開先のハッシュの値を上書きする場合は、警告が出ます。
pp ({ hoge: 1, **{ hoge: 2 } })
# warning: key :hoge is duplicated and overwritten on line 1
# => { hoge: 2 }
pp ({ **{ hoge: 2 }, hoge: 1 })
# => { hoge: 1 }
引数
配列の展開を使うと、位置引数にまとめて引数を指定できます。
def add(x, y)
x + y
end
ary = [1, 2]
pp add(*ary)
# => 3
ハッシュの展開を使うと、キーワード引数にまとめて引数を指定できます。Ruby3.0より前では、単にハッシュを渡せばキーワード引数を指定したものとして扱われていましたが、3.0以降では展開を明示する必要があります。(参考: https://www.ruby-lang.org/ja/news/2019/12/12/separation-of-positional-and-keyword-arguments-in-ruby-3-0/)
def full_name(first_name:, last_name:)
"#{first_name}/#{last_name}"
end
hash = {
first_name: "TARO",
last_name: "TANAKA"
}
pp full_name(**hash)
# => "TARO/TANAKA"
メタプログラミングを行うときには、位置引数(args
)とキーワード引数(kargs
)をまとめて取り扱うことがあります。
def call(func, args, kargs):
func(*args, **kargs)
end