Loading

Lisp不人気の謎に迫る

こんにちは、きたむらです。
3回目にしてはじめて技術らしいことに触れます。
Lispについて、その言語のとっつき悪さについて考察します。

関数型言語だから?

関数型言語のWikiページをみてみると、一応Lispも関数型言語という扱いになっているようです。
少し前に関数型ポエムで騒ぎが起きていたようですが、
自分は、そのあたりの顛末は風の便り程度の文章を少し読んだだけで、内容もよく知りません。
そもそも関数型という概念には興味がありませんし、あえて知る必要もないと思います。
そもそも、各言語を関数型、非関数型という分類で仕分けることはあまりないことだと思います。
というか、言語の仕様というよりかは、どのようにコーディングするか?の方が問題となるので
関数型言語だからとっつき悪い、という考え方はしません。

もっとシンプルな比較

最初の考察はSEO的なあれで、別にどうでもいいです。読む必要もないです。
本当のところはlambdaの概念が一番障壁になっているとは思いますが、
ここではあえて、別のアプローチをとります。S式がどーたらこーたらも言いません。

…というわけで、ここからが本題です。

Lispのとっつき悪さは、それはもうパっと見で分かることです。
…そう、1と1を足して変数に代入する。
この至極簡単な処理を各言語でみるだけで理解できます。
まずは、C/C++

int n = 1 + 1;

int型の変数nを作りそこに1と1を足したものを代入する。とても見慣れた光景です。
次はJava

int n = 1 + 1;

はい。同じです。
続いてPHP/Perl

$n = 1 + 1;

型宣言がなくなり、変数に$を付けなければなりませんが、文法的には同じようなもんです。
この勢いで、Ruby/Python

n = 1 + 1

ドルマークもセミコロンも必要なくなりました。すばらしくシンプルです。
さて、ここでお待ちかねのLispです。Lispは方言がいくつかあるのでここではSchemeを使います。

(define n (+ 1 1))

なんということでしょう!代入式なのに=がありません!
しかも1+1じゃなくて(+ 1 1)とか書いてあります。
今までのどの言語もかたくなに守ってきた
「代入には=を使う。左と右にあるオペランドをその真ん中の記号で処理する。」
という二つの法則をぶち破ってきました。
さらに、上記はいわゆるグローバル変数の定義であって、レキシカルスコープ内の変数(ローカル変数)だと

(let ((n (+ 1 1))) ())

とさらに意味不明な感じになります。(右から二つ目のカッコの中に書かれた処理の中でのみ変数nが使える)

…という風に、言語の思想や概念、実用性の前にまず見た目が他の言語と距離を置いている感じで
なかなか近づきがたいんじゃないかなぁ、と思ったりもするのでした。

おまけ、アセンブリだとどう書くの?

じつはアセンブリと言ってもCASL IIだったらみんなにも馴染みがあるんじゃないかな
と思って、おまけとして最後に書いてみます。

EXADD    START
              LD          GR0, =#0001      ;1をレジスタにロード
              ADDA     GR0, =#0001      ;レジスタの中身に1を足す
              ST          GR0, N               ;レジスタの中身をメモリ内のNの領域に保存
              RET
N            DS          1                       ;メモリの領域を確保してそのアドレスにNという名前のラベルをつける
              END

こちらも=もないし、数字も16進数で書かなければならないし、
一行では書けないし(レジスタに対するロードとメモリに対するストアを自身で書いて命令しないといけないの)で
わりととっつきにくい感じですね。

著者アイコン

著者きたむら

プログラマー的なサムシングにして歩くホワイト企業

関連記事