PHPでの名前付き引数のRFCについて

名前付き引数は、オプションの管理に便利な機能です。

グラフ作成の際に、軸名を指定すれば付くし指定しなければ省略されるだとか、 色を指定してもいいし省略すれば自動で適当につけてくれたりするなど

plot(x, y, linewidth=2.5)
plot(x, y, color="red",  linewidth=2.5, linestyle="-")

のようにできるとすごい便利。

で、PHPでも出来ないかなと思って調べたら出来なかったんですがメモ。

Python

Pythonは下のように引数名を指定して関数を呼び出すことが出来る。

def foo(a, b, c=8, d=9):
    print a, b, c, d

foo(1, 2)      # 1 2 8 9
foo(1, 2, d=4) # 1 2 8 4

便利。

Ruby

Rubyは以前は出来なかったけれど、2.0から出来るようになった。

def foo(a, b, c:8, d:9)
    print a, b, c, d,"\n"
end

foo(1, 2)      # 1289
foo(1, 2, d:4) # 1284

これも便利。*1

PHP

一方、PHPではこのような便利な記法は使えないよう。 ただ、default値の連想配列を用意して、呼ぶときも連想配列に突っ込んでもらって、 array_mergeすれば機能的には同じことが出来る。(昔のrubyのマネだけど・・・。)

<?php
function foo($a, $b, array $args) {
    $defaults = ['c' => 8, 'd' => 9];
    $args = array_merge($defaults, $args);
    
    print $a . $b . $args['c'] . $args['d'] . "\n";
}

foo(1, 2, []);         // 1289
foo(1, 2, ['d' => 4]); // 1284

上記のコードの良くないなーと思うところは、

  • やりたいこと以外の処理が多くなり、コードの見通しがあまり良くない。
  • オプションを指定しない時に、いちいち空のarray渡したくない。
  • 引数$argsはarrayだということは分かるが、中に何を入れれば良いかはコードかドキュメントを読まないといけない。
  • 無効なキーが渡された時(typoなど)に何のエラーもなく、ただ無視される。

のような点だと思う。

そして

今は使えなくてもいつか使えるようになるかなと調べたところ2012年に提案されていたらしい→PHP: rfc:namedparameters。しかし、

Discussion

We don't see the real need for named parameters, as they seem to violate PHP's KISS principle. It also makes for messier code.

でobsoleteだった。

と思ったら、2013年バージョンが再度提案されていました→PHP: rfc:named_params。 これによると

<?php
htmlspecialchars($string, double_encode => false);
// Same as
htmlspecialchars($string, ENT_COMPAT | ENT_HTML401, 'UTF-8', false);

みたいなことが可能になるらしい。 とても便利そうだけど仕様として複雑で、実装が大変な模様。 まだUnder Discussionなので、今後が気になる機能です。応援したいです。

結論

PHPでは出来ないので我慢しよう。

参考

  1. http://www.daisaru11.jp/blog/python-%E3%83%A1%E3%83%A2/%E9%96%A2%E6%95%B0%E5%BC%95%E6%95%B0%E3%81%AE%E5%8F%97%E3%81%91%E6%B8%A1%E3%81%97/

  2. Ruby 2.0.0リリース! – キーワード引数を使ってみよう

  3. » Ruby2.0のキーワード引数でオプショナルな引数にまつわる面倒事からさようなら TECHSCORE BLOG

  4. PHP: rfc:namedparameters

  5. PHP: rfc:named_params

*1:Pythonではfoo(1,2,3,4)とできますが、Rubyで同じことをするとArgumentErrorと言われるなど、ちょっと違いがある。