http://blog.livedoor.jp/dankogai/archives/50832431.html PHP については反響が大きいみたいだが Erlang の反響のなさは言語の知名度の差だなと思う。マイナーな言語だと アホなことを書いてもバレないからいいですね。
わたしも Erlang の言語仕様はダサいと思っていてべつに擁護するつもりはさらさらない。ありゃダメだ。モデルの良さと、実装(処理系)の良さと、統語論の良さはまた別である。 Erlang は実装は凄いし、モデルもほかに例がないので面白いが、それとシンタックスの善し悪しはそりゃ、ぜんぜん別の話である。
でもまあ、ある人が「ダメだ」と主張していることそのものには同意するとしても、その内実が間違っているのはやっぱり気になる。以下で書くのはそういう話。
構文の一貫性のなさ
関数定義と receive が似たような構文なんて意味不明に見えるかもしれない。でも実は似たような構文を取るものはほかにある。case、 if、try..catch、それに fun だ。
なぜこれはどれも似たような構文を持っているか。それは似たようなことをするからだ。簡単に言うと「パターンマッチをして、ローカルな変数束縛を作り、対応する式のならびを評価する」ということ。一方、変数への束縛はパターンマッチとして実現されているので、これがぜんぜん違う構文であることはまったく正当である。
関数と変数の名前空間が異なるという点については、 Common Lisp だってそうだし、そんなに重要なことだとは思わない。ただし、アトムと関数名が似たような名前空間を使っていて個人的には微妙だと思うことはある。
「OOに慣れた身からすると構文糖衣が多すぎる」というのはどういう冗談なのかよくわからない。念のために書いておくと、 receive にしても case にしても try..catch にしても、もちろんメッセージ送信にしても、べつに構文糖衣ではなく、歴とした構文である。「構文が多い」という主張だと思ってみても、それほど多いという気はしない。smalltalk みたいに非常にミニマルなコンセプトの言語よりは遥かに多いが、たとえば Ruby よりはずっと少ない。
なぜ別の構文としたかったかというのも推測はできる。推測するに、初期の Erlang はもっと Prolog 寄りの言語だったんじゃないだろうか、とね。 pred(A, B) のような表記はあくまでも述語であり、メッセージの送受信とは区別した方がいいと考えたのかもしれない。別ものだから別の構文を使うことにしたというわけだ。もちろんこれはわたしの勝手な推測。
余談として、メッセージ送信に ! という演算子を使うのは今となっては盲腸のようなもので、必然性は特にないだろうと思うし、わたしもイマイチだと思う。 Termite はこれを受けて ! 関数(マクロ?)を使うようだけど、もっとわかりやすい名前の方がいいんじゃないのかな。
無名関数の構文
上で書いたように fun は(あまり知られていない/使われていないが)複数のパターンマッチを書ける。これは優秀な機能で、ほかの関数型言語でこれができるのは、わたしは OCaml しか知らない(しかも OCaml では通常は fun で、それができるのは function という別の構文だ。あれは何とかならんものか)。
end はもちろん、どこが終端なのかわかりやすくすること、および receive や case や if や try..catch と構文構造を整えるためである(関数定義だけ end がない。これの方が一貫性に乏しいという気がするが、あったらとてもジャマだと思う)。文句を言うのは簡単だが、代替のより優れた構文というのはそう簡単には思いつかないし、 Rubyist のわたしは end があることに積極的な不満を感じない(そういえば Lua も end で終わる言語だな)。
ちなみに fun(Arg) -> mod:func(Arg) end のようなタイプの関数は fun mod:func/1 のような代替記法があり、実用上はそれほど繁雑にはなりづらい。もっとも、この代替記法は実用的な局面ではさっぱり短くならないという弱点も持っているのだが。
export って
モジュールの外からでも見える関数定義を指定するのが export である。 dankogai 氏が(たぶん)お気に入りの Haskell も同じ仕様だがあれも export していないとでも考えていたのかな。よく知らないのだけど、こういう不満をぶつけるということは perl は export するとほかのモジュールからモジュール名プレフィクスなしにいきなり参照できるのだろうか。名前の衝突に無力すぎると思うのだが。
そして、これは指摘もされているが、もちろんよく使うなら import してモジュール名プレフィクスを省く。
ただ、そこは Haskell のモジュールシステムの方が優れている点もある。というのは、個人的にはモジュールに別名をつけたいところ。 lists なんて打ちづらいモジュールはイヤだから、どこかでこれに「l」という別名をつけて、 l:map とかしたいのだね。これ、 Haskell だけじゃなく ML 系言語もできる技だが、 Erlang にはできない(と思う)。
それから、一気にエクスポートするなら -compile(export_all) という手もある。省略したら自動的にぜんぶエクスポートという方が私としては好みだが、どちらにせよきちんと指定しなさいというのもわかる(しかしなぜ -compile なのかはよくわからない。 -export_all か、 -export(all) でいいと思うんだが)。 DRY でないという主張は確かにその通りだが、 DRY でかつ、どれを export するかしないかを決めるというエレガントな構文はわたしには思いつかない(ダサいところで private { .. } のような構文を用意することとか……?)。
.(period)と,(comma)と;(semicolon)を使い分けている理由
ピリオドは定義の終わり(かつシェルでは入力式の終わり)、カンマは「式の並び」の区切り文字(または関数の引数の区切り文字)、セミコロンは関数定義などの「節(clause)」の区切り文字。ちゃんと意味は決まっている。使いわけているというか、ぜんぜん違うものだからそこ