Hatena::Groupcadr

わだばLisperになる このページをアンテナに追加 RSSフィード

2004 | 12 |
2005 | 01 | 02 | 07 | 10 | 11 |
2006 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2007 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2008 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2009 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2010 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2011 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 11 |

2008-03-05

cond、ifの変遷

| 19:20 | cond、ifの変遷 - わだばLisperになる を含むブックマーク はてなブックマーク - cond、ifの変遷 - わだばLisperになる

ポール・グレアム氏のコア言語としての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)
    (lambda ()
      (D E F)
      (G H I))
    (if (J K L)
	'(M N O)
	(lambda ()
	  (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に展開されるマクロとなり、なんとなく寂しいですね。

…いや、別に寂しくはないか(笑)

ゲスト



トラックバック - http://cadr.g.hatena.ne.jp/g000001/20080305