(44)Common Lispについて(1985) — #:g1

Posted 2010-08-01 14:35:00 GMT

TAO関係の論文を漁っておりますが、今回は、
-Common Lispについて
です。
題名からするとTAOとはあまり関係のない感じですが、内容はTAO開発者からみたCommon Lispという感じです。
大きく分けると、
+レキシカル・スコーピング採用について
+setf
+Keyword Parameter
+Package
+Sequence
+多重プログラミング
+オブジェクト指向プログラミング
+インタプリタとコンパイラ
について言及されています

レキシカル・スコーピング採用について

ダイナミック・スコーピングを減らすという流れには賛成だけれど、レキシカル・スコーピングまでは過剰仕様ではないかという指摘。
TAOでは、Static Scopingというものを採用していましたが、静的範囲を越えるところでは変数の探索モードを変えて外側の変数は、スペシャルでない限りアクセスできないようにしているとのこと。
どういう動作になるのか詳しくは分かりませんが、
(let ((x 8))
  (de bar ()
    x))

(let ((x 8)) (bar)) ;>>> エラー

こういうのはエラーで、
(let ((x 8))
  (declare (special x))
  (de bar ()
    x))

(let ((x 8)) (declare (special x)) (bar)) ;⇒ 8

これならOKということでしょうか。
レキシカル・スコープの問題としては、レキシカルクロージャーを生成する必要があるのでインタプリタでの動作が遅くなる、ということが挙げられています。
これだと、最近のScheme的なクロージャー万歳なプログラミングスタイルから見ると困るんじゃないかと思ってしまいますが、MIT系のLispマシンや、TAOには、closureという構文があり、
(defun f (x)
  (closure '(x)
    (lambda () (incf x))))

(!foo (f 8)) (funcall f) ;⇒ 9 (funcall f) ;⇒ 10 ...

のように明示的に取り込む変数を指定すればクロージャーは作れました。
また、「special変数が閉包に入らないのは実際の使用局面で不便を感ずることが多いのではなかろうか」というのは、closure構文では、スペシャル変数も取り込めるので、
(setf (symbol-function 'print-in-base-16)
      (let ((*print-base* 16.))
        (closure '(*print-base*) 'print)))

(print-in-base-16 10)) ;-> A ;=> 10

のような局面を指しているのだと思われます。(これはCommon Lispの仕様では無理です)

setf

TAOには、SETFより汎用的な代入機構があるので、これの解説です。

Keyword Parameter

インタプリタでは動作が遅くなるのと、それまでの慣用述語である、
(memq 'x '(x y z))

(member 'x '(x y z))

などが、
(member 'x '(x y z) :test #'eq)

(member 'x '(x y z) :test #'equal)

に統一されたのが人工的だなあ、とのこと。

Package

Symbolのパッケージへの帰属をpresentとownedに分けているのが複雑ではないかという指摘です

Sequence

オブジェクト指向の枠組みがあるのであればポリモーフィズムに吸収した方がスマートではないか、とのこと。
これは、現在でもCLで良く言われていることですね。(ANSI CLでCLOSが統合された時にも全面的な統一はされませんでした)

多重プログラミング

CLの仕様では何の規定もされていないが、実際に実現するのには、色々問題がありそうだ、という指摘です。
これも、ANSI CLでも規定されなかったので、現在でも問題になっていますね。

オブジェクト指向プログラミング

当時のCLtL1では、オブジェクト指向プログラミングは盛り込まれていませんでしたが、取り込む際の問題点が指摘されています。

インタプリタとコンパイラ

当時、Common Lispはコンパイルして使う言語との認識が広まっていて、当時の実装もインタプリタが極端に遅いことを指摘し、インタプリタとコンパイラの両立を掲げていたのに、実際のところインタプリタは付け足し機能のように使われていて、実質的には両立していないではないかとの指摘。
インタプリタの性能と使い勝手にこだわるTAOの姿勢が伺えます。
最近のCL実装は、SBCLにしろ、CCLにしろコンパイラ指向のものが多いのですが、デバッグ時のステップ実行等の使い勝手はあまり良くありません。
インタプリタだとどういう使い勝手だったのか自分も知りたいところです。

まとめ

とはいえ、CLを否定しているわけではなく良いところはTAOに取り込む方向で進んでいて、合せられるところは、極力CLに合せるとのことで、当時のLispマシンの処理系がそうであったように、CLのスーパーセットとしても機能するように考えていたように思われました。

comments powered by Disqus