タイプフル プログラミング(プログラムのセマンティック コンテンツの多くを型システムに静的に反映できるという考え方) を実践すると、多くの場合 (すべてではありません)、読みやすさのために名前付き引数が必要ないことがわかります。
List
OCamlの標準ライブラリにある次の例を考えてみましょう。それらがリストで動作することを知っていて、関数の名前 (うまくいけば明確です: 私たちは皆、適切な名前の選択を望んでいます) を使用すると、引数が何をするかについて説明する必要がないことがわかります。
val append : α list -> α list
val flatten : α list list -> α list
val exists: (α -> α bool) -> α list -> bool
val map: (α -> β) -> α list -> β list
val combine : α list -> β list -> (α * β) list
最後の例は興味深いことに注意してください。なぜなら、コードが何をするのかが明確ではないからです。実際にはいくつかの解釈があるでしょう。たとえば、 ではなく をcombine [1;2] [3;4]
返します。また、2 つのリストの長さが同じでない場合に何が起こるかも明確ではありません (障害モードは不明です)。[(1,3); (2,4)]
[(1,3); (1,4); (2,3); (2,4)]
例外が発生したり終了しない可能性のあるtotalではない関数は、通常、失敗のケースとは何か、およびそれらがどのように動作するかについて、より多くのドキュメントを必要とします。これは、私たちが純粋プログラミングと呼ぶものを支持する強力な議論の 1 つであり、そこでは関数のすべての動作が値を返すという観点で表現され(例外なし、観察可能な状態の突然変異、または非終了)、したがって、によって静的にキャプチャできます。型システム。
もちろん、これは十分にパラメトリックな関数に対してのみうまく機能します。彼らは何をするのかを非常に明確にするタイプを持っています。これはすべての関数に当てはまるわけではありません。たとえば、モジュールのblit
関数を考えてみString
てください (あなたのお気に入りの言語にもそのような例があるはずです):
val blit : string -> int -> string -> int -> int -> unit
は?
このため、プログラミング言語は名前付きパラメーターのサポートを追加します。たとえばOCamlには、パラメータに名前を付けることができる「ラベル」があります。同じ関数がStringLabels
モジュールで次のようにエクスポートされます。
val blit : src:string -> src_pos:int -> dst:string -> dst_pos:int -> len:int -> unit
その方がいいです。はい、場合によっては名前付きパラメーターが役立ちます。
ただし、名前付き引数を使用して、不適切な API 設計を隠すことができることに注意してください (上記の例も、この批判の対象になっている可能性があります)。検討:
val add : float -> float -> float -> float -> float -> float -> float * float * float
あいまいですよね?しかしその後:
type coord = {x:float; y:float; z:float}
val add : coord -> coord -> coord
それははるかに優れており、パラメーターのラベル付けは必要ありませんでした (おそらく、レコード ラベルは名前を提供しますが、実際にはfloat * float * float
ここでも同じように使用できます。値レコードが名前付き (およびオプション?) パラメーターを包含する可能性があるという事実も興味深い発言です)。
David M. Barbourは、名前付きパラメーターは言語設計の「松葉杖」であり、API 設計者の怠惰を改ざんするために使用され、それらを持たないことがより良い設計を促進するという議論を展開しています。すべての状況で名前付きパラメーターを回避して有益であることに同意するかどうかはわかりませんが、彼は確かに、私の投稿の冒頭にあるタイプフル プロパガンダに同意する点を持っています。抽象化のレベルを上げることで (よりポリモーフィック/パラメトリックな型またはより優れた問題領域の抽象化を通じて)、パラメーターの命名の必要性が減少することがわかります。