2008年11月11日火曜日

newLISP と CL/Scheme の比較

意訳、省略を含むので参考程度に眺めることを推奨します。

ところで newLISP ってなに?


Comparison to Common Lisp and Scheme

このページでは newLISP と他の標準な Common Lisp, Scheme とのいくつかの違いを明らかにする。newLISP 特有のアプローチを知りたいなら About を読んで下さい。

  1. CL と異なり、newLISP と Scheme は式のオペレータ部分を(引数に適用する前に)評価する。
  2. ラムダ式は自身を評価する。それらはリストの副タイプであり、他のリスト同様に扱えるファーストクラス・データオブジェクトである。

    newLISP ではラムダ式の自由変数の束縛はラムダ式の適用時にのみ行われる。

    newLISP のラムダ式は関数定義の後いつでも処理できる。
    (last (lambda (x) (+ x x))) => (+ x x)
    See the page: Scheme のクロージャと newLISP のコンテキストの比較
  3. 変数、関数の名前空間を共有している (Lisp-1)。 シンボルは大文字小文字を区別する。
  4. 全ての変数は基本的に動的スコープ。 けれども自身のコンテキスト内で定義することにより、静的/レキシカルスコープが得られるし、変数捕捉を避けることができる。
  5. ドット対が存在しない。代わりにセルがリストの一部ならば、そのセルは一つのオブジェクトと他のオブジェクトへのポインタを含む。ゆえに cons の挙動が他の LISP 処理系と異なる。
    ;; Common Lisp and Scheme
    (cons 'a 'b) => (a . b)         ; ドット対
    
    ;; newLISP
    (cons 'a 'b) => (a b)
    
    ;; LISP cells in Common Lisp and Scheme
    (cons '+ (cons '2 (cons '3 (cons (cons '* (cons '4 (cons '3 nil))) nil))))
    => (+ 2 3 (* 4 3))
    
    ;; LISP cells in newLISP
    (cons '+ (cons 2 (cons 3 (cons (cons '* (cons 4 3))))))
    => (+ 2 3 (* 4 3))
  6. ユーザ定義の関数の引数は全てオプショナルである。 代入されなかった引数は関数内部では nil と仮定される。
    ((lambda (x y z) (list x y z)) 'foo 'bar) => (foo bar nil)
  7. 必然的に、未束縛の変数は存在しない。 そのようなシンボルは最初の構文解析時に生成されて、現在の名前空間に nil として束縛される。
    (list foo bar baz) => (nil nil nil)
  8. ブール定数は nil/true 。 CL では nil はリストの終端という役割もある:
    ;; Common Lisp
    (cons 'x nil) => (x)
    
    ;; newLISP
    (cons 'x nil) => (x nil)>
    Scheme のブール定数は #t/#f が真/偽。
  9. シンボルとコンテキストを除く全てのオブジェクトは一度だけ参照される。 (ORO: Only Referenced Once) このルールにより CL, Scheme で使われる伝統的なガベージコレクションアルゴリズムなしに、自動的で、スタックベースなメモリ管理が出来る。
  10. マクロは引数を評価しない関数のようなもの。 結果としてマクロは組み込まれた基本関数のように振舞う。
    (define-macro (my-setq x y) (set x (eval y)))
    ;; もしくは変数捕捉を避ける衛生的なマクロとして
    (define-macro (my-setq) (setq (args 0) (eval (args 1))))
    変数を明示的に展開する組み込み関数として expand, letex がある:
    (let ((z 2))
      (expand (fn (x y) (* x y z))   ; fn は lambda の略記
              'z))
    => (lambda (x y) (* x y 2))
    
    (define (raise-to power)
      (expand (fn (base) (pow base power)) 'power))
    
    (define square (raise-to 2))
    (define cube (raise-to 3))
    
    (square 5) => 25
    (cube 5)   => 125
  11. 等価条件の判定は = のみ。 newLISP では値をコピーして渡すスタイルをとっている。
  12. インデックス機能 (implicit indexing)
    (let ((myList '(a b c (d e) f g))
          (v '(3 1)))
      (list (nth 2 myList)          ; using nth
            (myList 2)              ; using implicit indexing (1)
            (myList -3 0)           ; using implicit indexing (2)
            (myList v)              ; with address vector
            (1 2 myList)            ; implicit rest, slice
            ))
    ;=>(c c d e (b c))

newLISP の内部についての詳細は以下を参照のこと:


Change Log

  • 2008-11-11 訳してみたので公開
  • 2008-11-30 加筆修正
    高階関数 (higher-order function) とファーストクラスオブジェクト (first-class object) はどう見ても別物です。なに勘違いしてるんだ自分…

0 件のコメント:

コメントを投稿