関数のパラメタの位置に悩む。
OCamlのList.nthはリスト・位置の順でパラメタが要求される。HaskellのData.Listの(!!)も同じくリスト・位置の順だが、これは リスト !! 位置 という記述が自然だからまぁそうなんだろう。OCamlのList.mapは関数・リストの順でパラメタが要求される。HaskellのData.Listのmapも同じく関数・リストの順だ。関数を固定した特定機能のmapを作る(カリー化する)ことを考えるとこの順番が自然なんだろう。OCamlのList.memは値・リストの順でパラメタが要求される。HaskellのData.Listのelemも同じく値・リストの順だ。これの場合List.nthとの差はあまり考えられないが、List.nthはリストが先頭でList.memはリストが末尾。List.memはList.mapと同じ扱いになる。どうもなるべくなら主要なパラメタは末尾にというのが関数型言語の流儀なんだろうか。カリー化と関わるからそれなりに意味や意義はあるんだろう。
OCamlのoutputはチャンネル・バッファ・開始位置・長さの順だが、主要なパラメタであるチャンネルが先頭にある。I/O周りはUnixのシステムコールになるべく合わせるということだろうか。Unixのwriteはファイルデスクリプタ・バッファ・長さの順で似ている。I/Oとそうでないもので主要なパラメタの位置を分ければ良いのだろうか。HTTPリクエスト・レスポンスはI/Oだろうか。XMLの要素はどっちなんだろう。そもそもCのランタイムのfwriteはバッファ・要素長・要素数・ストリームで主要なパラメタが末尾になっている。Unixは概念のレベルによってバラバラなのである。Windows APIは主要なパラメタがハンドルで、普通は先頭にある。主要なパラメタが末尾になるのは関数型言語の関数型っぽい関数の特徴なのかもしれない。しかしString.containsやString.subなどは主要なパラメタである文字列が先頭になっている。I/O扱いなのかこれは? Haskellはこの点は大丈夫だ。文字列なんて不純なものは存在しないから。
Scalaはそもそも主要なパラメタがクラスオブジェクトで関数はそのメソッドになるので、悩むことなく決まっている。
OCamlにはList.takeはない。自分で書くときにはHaskellに合わせて数値・リストにしてある。
OCamlのList.fold_rightのパラメタの末尾はリストではない。HaskellのData.Listのfoldrはちゃんと末尾がリストになっている。OCamlのList.fold_rightに深遠な理由があるのか、単なる手違いなのかは不明。でも、こういうのは迷惑。
迷惑といえば、色々な言語の文字列のsplit関数のデリミタのパラメタが、もうなんというか勝手過ぎ。Pythonは文字列。Javaは正規表現。Scalaは文字または正規表現。.NETは文字の配列。OCamlにはそもそもないので、自分で書いたのは文字列の配列にした。BatteriesのString.splitはいくらなんでも使い勝手悪過ぎ。この程度のことで例外を投げるとか勘弁して欲しい。
2015.03.10
OSTRACISM CO.
OSTRA / Takeshi Yoneki