注意。このエントリはRuby 2.0に入るかもしれない機能について述べていますが、本機能が本当に2.0に採用されるかどうかは、未定です。
「まだあるのか」とか思われそうだけど、まだあるんです。
今度は長年採用すると言いつつ、ほったらかしの最右翼、キーワード引数である。 調べたら、キーワード引数については、2003年のRubyConfではすでに話題にしている。 どんだけ前から口にしてたんだ。「やるやる詐欺」だな(苦笑)。
その時の仕様はこんな感じ。
def foo(a, b: 42, **keys) p [a,b,keys] end foo(1) # => [1,42,{}] foo(2, b: 5) # => [2,5,{}] foo(3, b: 4, c: 6) # => [3,4,{:c=>6}]
まあ、そんなに悪くない。基本的にはこの線を踏襲しようと思う。 文法としては、ブロック引数の直前に
keyword: value,..., **keys
というキーワード引数を置くことができる、というもの。 Pythonと違ってキーワード引数は明示的に指定しなければならない。 通常の引数名が勝手にキーワードになったりはしない。
問題はrest引数と組み合わさった時。
def baz(*rest, a:4, b:0, **keys) ... end
として、以下の呼び出しを行ったらどうなるか。
baz() # rest=[],a=4,b=0,keys={} baz(1) # rest=[1],a=4,b=0,keys={} baz(a:1) # rest=[],a=1,b=0,keys={} baz(a:1,b:2) # rest=[],a=1,b=2,keys={} baz(1,2,b:2) # rest=[1,2],a=4,b=2,keys={} baz(c:2) # rest=[],a=4,b=0,keys={c:2}
つまり、以下のルールに従う。
なお、※の部分はRubyConf 2005のキーノートで紹介したものと動作が違う。
この仕様ではキーワード指定はあくまでも通常引数の一部なので、 通常引数の引渡の時には *rest で受けて、 foo(*rest) と呼び出せばよい(はず)。
呼び出し側のキーワード引数は結局は引数リスト末尾のハッシュに過ぎないので、 呼び出し側では foo(**keys) のような文法は(本来は)不要。 ただし、対称性と型チェックのために採用する可能性は、なきにしもあらず(あんまり積極的ではない)。