なぜLispは「括弧が多い」印象になるのか?
最近、全然Lispネタ書いてないなぁとか思って、書き散らかして完成しないで下書きだけが増えて言ってます。
先に謝っておきますが、なんとなくうだうだ考えたりソース書いたりして、グダグダなエントリ。ごめんなさい。
しかも、ずっと前の話題で、すっげぇ遅れている感。
Lispは括弧が沢山ある?
まぁなんと言いますが、これほど多くの人に指摘されて、これほど多くのLisperが反論して来た問答は無い気がする。Lispを見たこと無い人がまずLispコードを見たらまず出てくる感想がコレでだと思う。
Lispは本当に括弧が多いか?
じゃあ実際にはLispは括弧が多いかと言われたら、このブログが反論になるだろう。
http://e-arrows.sakura.ne.jp/2010/08/is-lisp-really-has-too-many-parenthesis.html
しかし、それでは上記でLispに疎い人が主張する主観と一致しない。それに、実は僕もLisperでありながらLispコードをぼんやりと見ると、多いと思ったりする。ではなんで「括弧が多い」と思うのか?
主観的な「括弧の多さ」
上記のブログで書かれているコードのJavaScriptとCommon Lispを比較してみよう。以下のコードをぱっと見てみよう。あくまでも、ぱっと見だ。良く読んではいけない。
var fact = function (n) { return n ? n * fact(n - 1) : 1; }; for (var i=1; i<=(arguments[0]||1); ++i) { print(i+"! = "+fact(i)); }
(loop for i from 1 to (or (parse-integer (cadr *posix-argv*)) 1) for acc = 1 then (* acc i) do (format t "~a! = ~a~%" i acc))
なぜこの二つを選んだのは、何となくです。
さて、どっちが括弧が多いと思う?
ぱっと見ると、Common Lispの方が多く見える気がしません?(僕だけ?)
コレに関して実験心理学的な検証はしたい。だが、面倒なんでだれかやってくれるかなー。
しかし上記のエントリによると、Common Lispが12個で、JavaScriptが16個。実はJSの方が多いのだ。
と何となく考え続けていると、知人から以下の指摘があるんじゃないかという意見を貰った。
- 括弧の密度
- Lisp書き方は括弧が目立つ
- 大括弧、中括弧を書かない影響
括弧の密度
なるほど、如何にソースコードの括弧が少なくても、コード自体が短ければ、括弧が多く見えるのかもしれない。
密度を正確に公平に拘って、議論しようと思えば、延々と議論が出来るが、面倒なので、おおざっぱに括弧/行数が密度だとする。
上記のソースコードは括弧/行数を求める、JavaScriptは16/6=2.66666..., Lispは12/3=4で、JSの方が括弧/行数は小さくなる。
Lispは括弧の密度が高いのだ。
Lispの書き方は括弧が目立つ?
どういうことかといえば、他の言語よりLispは括弧が目立つ一にある場合が多いのじゃないかと思った。多くの場合は先頭に括弧があることが多いし、他のシンボル空白を空けて括弧を書くことが多い。一方、他の言語だと括弧は大体、ソースコードの行の後ろの方にある。それが逆に括弧の「多さ」を強調する結果になっているのかもしれない。
階乗を求める関数で比べてみよう。
function fact(n)( if( n == 0 )( return 1; )else( return (n * fact(n - 1)); ));
元のコードはJSだが、比較のために中括弧を全部丸括弧にした。あとシンタックスの色づけを切った。
(defun fact (n) (if (= n 0) 1 (* n (fact (- n 1)))))
これはCommon Lispのコードだ。
括弧の数はどちらも同じ14個である。行数で言えばどちらも4行である。どうだろう?Lispの方が多く感じないだろうか?
中括弧と大括弧を書かない影響?
ほとんどのLispは中括弧や大括弧を書かないことが多い。(Gaucheとか大括弧を用いている例はあるが)。それも印象に影響を与えているのでは?と言う話。
さっきのJSの中括弧を全部丸括弧に戻したコードがこちら。
function fact(n){ if( n == 0 ){ return 1; }else{ return (n * fact(n - 1)); }};
比較のために再掲。
function fact(n)( if( n == 0 )( return 1; )else( return (n * fact(n - 1)); ));
なんか微妙だ。バイアスが掛かっているのかもしれない。あんまり中括弧や大括弧は関係が無いかもしれない。
どちらかというとソースコードの見やすさで言えば、中括弧の方だろう。だが、それはなんか括弧の多さには直接には関係が無い気がして来た。