Ruby 2.0.0 のキーワード引数
初稿:2013-02-24
書いた人:遠藤侑介 (@mametter)
はじめに
Ruby 2.0.0 のリリース、おめでとうございます。
本稿では 2.0.0 の新機能の一つである、キーワード引数についてご紹介します。
一目でわかるキーワード引数
ログを出力する機能の例。
あまりに自然すぎて、何が新しいのかわからない?
説明
1.9 でも、呼び出し側のキーワード引数はできていました。
このキーワード引数は { :level => “INFO” } というハッシュとして当該メソッドに渡されます。
受け取り側でこのハッシュを分解する処理が必要でした。
これだけならそんなに複雑じゃないんですが、細かいことを考え出すと段々面倒になります。
例えば
- 可変長引数も組み合わせたい
- 知らない引数が渡された時はわかりやすく例外を出してほしい
- nil を渡したいこともあるんです
など。コードとしてはこんな感じになります。
いちいちこういうの書くのは面倒くさいよね、というだけの動機で生まれたのが本機能です。
本機能を使えば、冒頭の通り、極めて簡潔にキーワード引数を分解できます。
もう少し詳しく
このメソッドは引数無しで呼び出すと、level: “ERROR”, time: Time.now が渡されたのと同じように動きます。
キーワード引数の順番は順不同です。(ただし、他の種類の引数と順番を変えることはできません)
片方だけ指定することもできます。
知らない引数を与えると例外を投げてくれます。
例外にしてほしくないんだ!という人は、** 引数で残りのハッシュを明示的に受け取ればいいです。
また、オプション引数や可変長引数などと組み合わせることも可能です。(極端なのはあまりお勧めしませんが)
制限
可変長引数でハッシュを渡す場合は要注意。
キーワード引数とみなされて最後の 1 個が消えてしまいます。
また、unknown keyword の例外を抑制する ** 引数の引数名は省略できません。
(この挙動はどうなのかなあ、と書いてるうちに疑問に)
さらに、元々キーワード引数っぽいことしていた関数を本機能で書き換えようという際の注意点ですが、キーワードに Ruby の予約語を使うことはできません。
↑は動くことは動くのですが、if というローカル変数にアクセスできないので読みだすことができません。こういう場合はやむを得ないので ** 変数を使ってください。
おわりに
2.0.0 では、キーワード引数を受け取るための仮引数の構文が追加されました。
実装はほぼ構文糖なので、実のところそれ自体は大した機能ではありませんが、
Ruby の文化としてキーワード引数が第一級になったという事実が重要かと思います。
今後キーワード引数を使った API を見かける機会が増え、
あなたの Ruby 生活に彩りを与えてくれると思っています。
筆者について
遠藤侑介。
Ruby コミッタ (アカウントは mame)。Ruby のテストカバレッジをあげたり、1.9.2 のリリースマネージャ補佐をやったり、2.0.0 のリリースマネージャをやったり。