ぱたへね

はてなダイアリーはrustの色分けができないのでこっちに来た

Lisp in Small Pieces 1.6 Representing Function

Lisp In Small Piecesの1.6のまとめ。スコープの所が良くわかっていない。

(自作処理系の)関数の実装には、(Schemeの)関数を使うのがよい。最も簡単な実装。

(define (invoke fn args)
    (if (procedure? fn)
        (fn args)
        (wrong "Not a funstion" fn)))

練習問題1.7、1.8でさらに詳しくやるっぽい。

関数適用におけるエラーについて

  • 関数の場所(listのcar部分)にある項を評価する
  • その値が関数適応できない値の時、エラーを発生させる
  • 引数を左から右へ評価する
  • 引数の数と、関数のarity(オペランドの個数)の数を比較し、同じなら関数適用を行い、数が違う場合はエラーを発生させる。

最初に引数の数をチェックしてもよい。

1.6.1 Dynamic and Lexical Binding

全ての評価は、特定の環境下で行われる。3章ではもっと込み入った構造(unwind-protectなど)を取り扱う。

もう一つの大事な点は、はダイナミックバインディングとレキシカルバインディング。レキシカルLispでは、関数は、その変数によって拡張された、定義時の環境で評価される。ダイナミックLispでは、関数は現在(実行時)の環境を拡張する、つまりアプリケーションの環境で評価される。

最近の流行はレキシカルLispである。pure schemeでは、たった一つのbinidng フォームlambdaを持つ。

(define (foo x) (list x y))
(define (bar y) (foo 1991))

lexical Lispの時、fooの中のyはグローバル変数のyを示す。

(define y 0)
(define (bar 100) (foo 3)) ;; => ((1991 0) (3 0)) in lexical Lisp
(define (bar 100) (foo 3)) ;; => ((1991 100) (3 0)) in dynamic Lisp

新しいスペシャルフォーム function を導入する。Lambda formを引数に取りclosureを作る。これにより、関数と定義時の環境が関係づけられる。このクロージャが適用されたとき、現在の環境を拡張するのではなく、定義時の環境を拡張する

Common Lispでは、(declare (special x))でダイナミックスコープになる。

1.6.2 Deep or Shallow Implemantation

環境をalistで表現した場合、検索(lookuo)のコストはリストの長さに比例する。これをdeep bindingと言う。もう一つ、shallow bindingという実装方法がある。

http://www.geocities.co.jp/SiliconValley-Bay/9285/ELISP-JA/elisp_147.html

良くわからないけど、速度に関する実装の話なので、とりあえず置いておく。