コンテンツへスキップ
ものがたり
戻る

named arguments considered harmful

珍しく言語論をぶってみるよ。

VBなんかにある名前付き引数は有害で、あんなものさっさと無くなった方が良いと思う。理由は、関数の引数名なんていう、通常は注意を払わないものが、結果的に公開APIで(も)意味を持ってしまって、単なるパラメータの変更が、公開APIの互換性を損なうことになるからだ。

たとえばこんな関数があったとしよう。

public function GetMessage (string messageID, string langage)

これを一旦安定性の求められるAPIで公開してしまったら、その後引数名を language に訂正することは出来ない。なぜなら、ユーザーが書いた以下のようなコードがエラーになってしまうからだ。

string msg = GetMessage (messageID = messageIDs.Hello, langage = "ja")

スペルミスなんて関数名でも起こりうるから、パラメータ名だけ特別視する必要ないじゃないか、と思うかもしれない。でもそんなのってバカげていると思わない?

同じ引数の組み合わせの関数をバージョンアップして、languageだけでなくregionも受け付けられるようにしたらどうなるだろう。

public function GetMessage (string messageID, string languageOrRegion)

これももはや互換性のない変更になる。パラメータ名が異なるというだけで。

つまりこれって、将来のコードに対する拡張性を無駄に制約していることになるわけだ。その自由の損なわれ方に比べて、名前付き引数が示すことができるメリットって、とっても小さいんじゃないか?

C#のアトリビュートみたいな文法なら、公開プロパティだし、問題ないのだけど。

(これは前々から思っていたことなのだけど、そんなくだらない理由でmonoのcorcompareが無駄に互換性エラーをレポートするようになったのが実に気にくわないので書いてみた。VBなんて積極的に死滅してもらいたいし、VB.NETしか開発言語として生き残っていないような未来なら、アメリカで法律屋にでもなってやる。)

追記: コメント欄も面白いのでご参考あれ。

派生クラスでオーバーライドされたメソッドの引数名をどう扱うかっていう問題もありそう

ちなみにVBが嫌いだからこう主張しているってわけではないですヨ。.NET言語で言えばilasmも同様の問題をかかえている(starg, ldarg)。


コメント

nurse — 05/27/2008 04:46:54

この主張は「VBなんかにある名前付き引数」批判であって、「名前付き引数」批判とは微妙に異なるという理解でいいのですかね。
いや、「名前付き引数」を正しく実装・利用するには、
* 引数が公開されるという意識改革
* 引数名が変わる場合への言語的サポート (オーバーロードの強化?)
などが必要になるであろうと。

atsushieno — 05/27/2008 05:33:06

自分の書いている対象がどれくらい幅広いスコープのものであるか、自分でも理解しているかどうか怪しいところですが、同旨の議論はたとえばPythonの名前による引数指定なんかにも当てはまるように思います(Pythonは全くいじっていないので「言語的サポート」があるかどうかは分かりませんが)。

「名前付き引数」ってもしかして多様な意味のあるジャーゴンなんでしょうかね?

ちなみにユーザーの意識の問題というより、将来の変更に対してこんな風に脆弱な仕様は好ましくない、という言語設計の問題だと考えています。

atsushieno — 05/27/2008 05:34:38

(脆弱って書くとvulnerabilityみたいだな。融通のきかなさ、とでも言い換えておきます。)

nurse — 05/27/2008 14:18:04

まず、ここでの批判はPythonには確かに当てはまるのですが、JavaScript 2.0草案のものにはあてはまりません。
http://www.mozilla-japan.org/js/language/js20/rationale/named.html
「多様な意味」とか「ジャーゴン」だと大げさになってしまいますが、VB.NETやPythonにある「名前付き引数」が、世の中の「名前付き引数」の全てではありませんね。

「オブジェクト指向」だといかにも「ジャーゴン」ですが、「配列」は実はリストだったりとか、「ハッシュ」が順序を保持したりとか、まぁ色々ありますな。

「意識改革」というのは語弊があったかもしれません。言いたかったことは、「関数の引数名なんていう、通常は注意を払わないものが、結果的に公開APIで(も)意味を持ってしま」うのが問題ないならば、注意を払わせればいいと。もっと言うならば、注意を払わせるような言語デザインをするべきであろうと。JavaScript 2.0 草案では「named」をつけさせることで、これの解決を試みています。
拡張性もJavaScript2.0草案だとlanguageとlangage両方で受け取ってから揃えるとかできますし、言語側でもっとサポート可能でしょうね。

つまるところ、仰っているとおりこれはVBやPythonの言語設計の問題であり、「名前付き引数」一般の問題ではないのではないか、と。

atsushieno — 05/27/2008 14:42:22

なるほど、Javascript 2.0草案のような言語は実在するのですね(いや草案なんだから実在というのは変か…)。上記のような意味での問題は解決されているので、確かに「名前付き引数」に例外なく当てはまる問題ではありませんね。

kmizushima — 05/28/2008 14:54:14

JavaScript 2.0草案以外では、
OCamlのラベル付き引数などはどうでしょうか。OCamlでは、
let get_message ~message_id:msg_id ~language:lang = …
のような形で、名前付き引数を定義することができます。
ここで、message_idとlanguageが呼び出し時に使うラベル
名で、仮引数名であるmsg_idとlangとは明確に区別されている
ため、仮引数名という公開APIには現れないものと、ラベル名
という公開APIに現れるものを区別して書くことができます。

atsushieno — 05/28/2008 18:58:53

うーん、OCamlも全く知らないのですが、見た感じ、公開APIにおける名前は1つしかつけられないんですよね。結局将来の変更については非互換になるように思います。

kmizushima — 05/28/2008 21:37:41

確かにその通りです。ただ、OCamlのラベル付き引数では、仮引数名という内部的な識別子が公開APIにそのまま露出するわけではなく、プログラマが公開することを意図した名前のみが公開されるわけです。意図して公開した名前の変更に際して非互換性が生じることが、そこまで問題なのでしょうか。ラベル付き引数の無い言語であっても、例えば、一度APIとして公開された関数の名前を変更することは簡単にできないわけで、ラベル付き引数の命名に当たっては、公開APIの名前を付けるのと同程度の慎重さが求められる、ということが周知されていれば良いのではないかと思うのです。

atsushieno — 05/28/2008 21:49:44

ああ、なるほど意図を取り損ねました。意識して公開APIの一部としているのだから問題ないではないか、ということであれば、確かにおっしゃる通りですね。


この記事を共有:

前の記事
trailing comma
次の記事