3

(print x) は評価したいものを正確に出力しますが、(eval x) は失敗しますが、x を実行すると動作します! 私は何が欠けていますか?
なぜこれがうまくいかないのか、または私が何かばかげたことをしているのか教えてください。
動的サイズのテーブルを印刷し、ラムダ変数を設定して、最終的にテーブル内の各セルの式を評価しようとしています。
ところで、eval が失敗する理由がわかりました。(eval x) はマクロレットを失っていますが、なぜ?!
これは機能します:

(defvar varlist '(a b c d))
(defvar vvars   '(c d))
(defvar hvars   '(a b))
(macrolet ((AlternateVariable (var &rest body)
               `(dolist (,var '(nil t)) ,@body))
           (AlternateVariables (varlist &rest body)
               (if (null varlist)
                   (cons 'progn body)
                   `(AlternateVariable  ,(car varlist)
                    (AlternateVariables ,(cdr varlist) ,@body)))))
      (let ((listvarlist (cons 'list varlist)))
        (print
         `(AlternateVariables ,(reverse vvars)
            (AlternateVariables ,(reverse hvars)
              (format t "row=~S~%" ,listvarlist) ))))
      nil)

そして、それは私が望むものを印刷します:

(alternatevariables (d c)
 (alternatevariables (b a) (format t "row=~S~%" (list a b c d)))) 

その「print」を「eval」に変更すると、

; in: alternatevariables (d c)
;     (B A)
; caught warning:
;   undefined variable: a

しかし、(マクロレット内で) 印刷されたものを実行すると、動作します!

(macrolet ((AlternateVariable (var &rest body)
               `(dolist (,var '(nil t)) ,@body))
           (AlternateVariables (varlist &rest body)
               (if (null varlist)
                   (cons 'progn body)
                   `(AlternateVariable  ,(car varlist)
                    (AlternateVariables ,(cdr varlist) ,@body)))))
  (alternatevariables (d c)
    (alternatevariables (b a) (format t "row=~S~%" (list a b c d))))
  nil)

そしてそれは印刷します

row=(nil nil nil nil)
row=(t nil nil nil)
row=(nil t nil nil)
row=(t t nil nil)
row=(nil nil t nil)
row=(t nil t nil)
row=(nil t t nil)
row=(t t t nil)
row=(nil nil nil t)
row=(t nil nil t)
row=(nil t nil t)
row=(t t nil t)
row=(nil nil t t)
row=(t nil t t)
row=(nil t t t)
row=(t t t t)
nil

「eval は悪」と聞いたことがありますが、正しい評価順序を取得し、いくつかの引数を評価するためにバッククォートが必要ですが、他の引数は評価しません。Print は優れたデバッグ ツールですが、eval では何かが欠けています。eval はマクロレットを失いますか?

! それでおしまい。これら 2 つのマクロレット マクロを defmacros として定義すると、eval が機能します。

どうして?!Eval はマクロレットを失っています。(私はマクロレットを初めて使用し、Lisp の天才ではありません)
または、eval なしでこれを行うにはどうすればよいですか?
私のコードに関する一般的なメモもいいでしょう。これは複雑すぎますか?
また、マクロでエラーが発生すると、厄介なエラー メッセージが表示されるようです。それについて何か助けはありますか?

$ sbcl
これは、ANSI Common Lisp の実装である SBCL 1.1.2-1.fc18 です。

4

1 に答える 1

5

EVAL in Common Lisp only evaluates in a current dynamic environment and the null lexical environment. Enclosing it in lexical constructs like MACROLET, LET, ... or similar is not going to work.

于 2013-07-05T07:48:32.820 に答える