#:g1: cond、ifの変遷

Posted 2008-03-05 10:20:00 GMT

ポール・グレアム氏のコア言語としてのArcについての最近のエッセイで、condの括弧の多さへの批判と、これを放置していたのは、既存の価値観に捕われていた所為じゃなかろうか?のような指摘があったのですが、いやいや、condや、ifも色々面白い変遷があったようだし、そうでもないんじゃないか?、と思ったので、適当に纏めてみました。
もちろんpgはそういうことが言いたいんじゃない!ということになろうかと思いますが、私は、プログラミングに興味はあまり無く、言語の歴史や変遷に興味があるので :)
まず私のスタンスですが、condの括弧は多いとは感じません。R6RS風の角括弧も読み難く感じます。この辺は全く感覚的なものだと思うので、どうしようもないですね。特に理由もないですし。
ということで、Arcのifはcondより読み難いと思っていて、cond万歳な価値観であり、下記にもそういうバイアスがかかっていると思います。
それはさておき、cond、ifの歴史的変遷を眺めてみたいと思います。

M式 1958年頃

[a[B;C] → prog2[d[E;F];g[H;I];
 j[K;L] → (M N O);
 T → prog2[p[Q;R];s[T;U]]
まず一番最初は、M式ですが、別にcondという名前もifという名前も付いていなくて、[]で纏められた条件式の集まりです。条件が真ならば、→の右側が評価されます。式はセミコロンで区切られます。
また、'(a b c)は、(A B C)と表現され、(list 'a 'b 'c)は、list[A;B;C]と表現されます。つまり括弧が2種類あって意味的に違ったものを表現しています。
無理にS式風に書いてみると、
[(a b c) → (prog2 (d e f) (g h i))
 (j k l) → '(m n o)
 'T → (prog (p q r) (s t u))]
という感じです。つまりM式は既にR6RS風であり、また、pgが問題にしている括弧の多さ問題もなかった訳ですね。まあ、代わりに矢印があるわけなのですが。
上記を当時のS式で書くと
;; S式
(cond ((a b c) (prog2 (d e f) (g h i)))
      ((j k l) (quote (m n o)))
      ((quote t) (prog2 (p q r) (s t u))))

となります。condの実行節が暗黙のprognになっているかどうか不明なのですが、自分がエミュレータ試しても、論文を眺めても暗黙のprognになっているという記載は見当たりません、また、省略されるとnilが返るということもなく、省略できません。この辺本当はどうだったんでしょう。pg氏は、暗黙のprognだった、って書いてるんですけども…。M式でも暗黙のprognってどう表現して良いか分からないし謎です。
それはさておき、ここからずっと下って、1978年頃なのですが、IFが登場して来ます。

MacLISP、Zetalisp、Emacs Lisp 1978年頃

(if (a b c)
    (progn
	(d e f)
	(g h i))
    (if (j k l)
	'(m n o)
      (p q r)
      (s t u)))
CONDがあるので、こういう書き方はされないのですが、敢えて書くとこうなります。
else節が暗黙のprognになっていますが、
(defmacro if (pred then &rest else)
  `(cond (,pred ,then)
	 (t ,@else)))
のようなcondに展開されるマクロになっているので、おまけでそうしてるんじゃないかと思ったりします。
このifの由来ですが、The Evolution of Lispによれば、schemeからの影響じゃないだろうかとのことで、Schemeには、1975の最初からifが存在します。
これは、else節は暗黙のprognになっていません。

SCHEME 1975年

(IF (A B C)
    (BLOCK
      (D E F)
      (G H I))
    (if (J K L)
	'(M N O)
	(BLOCK
	  (P Q R)
	  (S T U))))
これまた、若干無理矢理な書き方で、こういう時は素直にCONDを使うようです。

…ということで、最初の20年位はifがなく、whenやunlessと登場時期は一緒だったようなのですね。

MacLISP Multics Emacs 1978 / Bernard S. Greenberg

そういう経緯もあり、1980年台初頭位まで、LISPにおいてのifの首はまだ座っておらず、変種が結構あります。
(if (a b c)
    (d e f)
    (g h i)
    else
    (if (j k l)
	'(m n o)
	else
	(p q r)
	(s t u)))
これは、Multics Emacsの中のifマクロの例。
elseで区切り、then節もelse節も暗黙のprognになっています。

Franz Lisp 1980頃? John Foderaro

(if (a b c)
    then (d e f)
         (g h i)
  elseif (j k l)
         '(m n o)
    else (p q r)
         (s t u))
これは、Franz Lispのifマクロの例。Franz Lispの処理系のソースでは、condが殆ど使われておらず、殆どこのifマクロです。
最近のAllegro CLでも、if*として存在しています。
このifマクロは、condと機能的に完全に等価で、(if 'foo thenret)と表現することにより、(cond ('foo) )のようなことも可能です。
また、多重の括弧の読みやすさへの配慮として、R6RS風に角括弧も使えました。
(cond [(a b c) (prog2 (d e f) (g h i))]
      [(j k l) '(m n o)]
      ['T (prog2 (p q r) (s t u))])

INTERLISP

また、Interlisp系でもいつ頃なのかはっきりしませんが、
(if (a b c)
    then
    (d e f)
    (g h i)
    else
    (if (j k l)
	then
        '(m n o)
        else
	(p q r)
	(s t u)))
のように書けるようになりました。thenとelseのキーワードがあり、どっちの節も暗黙のprognです。

Common Lisp 1984

それで 1984年 Common Lispですが、Schemeと同じく実行節は暗黙のprognになっていません。
(if (a b c)
    (progn
	(d e f)
	(g h i))
    (if (j k l)
	'(m n o)
	(progn
	  (p q r)
	  (s t u))))

Arc 2008年

そして、2008年 Arcは、condから各節の括弧を省略した形をifという名前にしました。
(if (a b c)
     (do (d e f)
	 (g h i))
    (j k l)
     '(m n o)
    (do (p q r)
	(s t u)))
という風にcond、ifにも色々あったようなのです。
今日の状況からすれば、プログラミングをLISPから入門するということはないと思われ、condは異質なものと感じられることが多いと思います。
cond自体もifに展開されるマクロとなり、なんとなく寂しいですね。
…いや、別に寂しくはないか :)

comments powered by Disqus