2

Lisp は初めてで、ANSI Common Lisp の第 8 章のテキスト ジェネレーターの例について読んでいました。この例に従って、LET 変数「prec」のスコープで関数「see」を定義しました。

(let ((prec '|.|))
  (defun see (symb)
    (let ((pair (assoc symb (gethash prev *words*))))
      (if (null pair)
        (push (cons symb 1) (gethash prev *words*))
      (incf (cdr pair))))
    (setf prev symb)))

それをlispファイルに保存しました。

その後、REPL に戻り、コンパイル済みのファイルをロードした後に see を呼び出そうとすると、エラーが発生しました。

The variable PREV is unbound. [Condition of type UNBOUND-VARIABLE]

see を正しく呼び出すにはどうすればよいですか? そして、レキシカルクロージャーとは何ですか?私はすべて混乱しています。

助けてくれてありがとう。

4

1 に答える 1

4

囲んでいるフォームのprec代わりに入力したようです。prevlet

レキシカル クロージャは、レキシカル環境の一部を「閉じる」関数です (名前の由来)。ここで繰り返そうとはしませんが、本質的にletは、語彙環境を操作する最も一般的な方法である Lisp のクロージャーの優れた紹介がたくさんあります。この場合、 のバインディングを追加するprevと、フォームの本文内のコードで使用できるようになります。関数seeはこのバインディングを「閉じる」ため、これらの呼び出しを行うと、フォームseeによって確立されたレキシカル環境にいることはできなくなりますが、各呼び出しはそれにアクセスできます。letある意味で、関数定義はバインディングを持っていると言えます。

の名前を誤って入力したように見えるためprev、関数は、コード内のその時点で確立されていないバインディングを参照しようとしています。

于 2012-09-13T10:56:28.710 に答える