문제

공통 LISP의 변수에 S- 표현이 바운드가 있습니다.

(defvar x '(+ a 2))

이제 호출 할 때 정의 된 범위의 표현식을 평가하는 함수를 만들고 싶습니다. 나는 이것을 시도했다 :

(let ((a 4))
  (lambda () (eval x)))

그리고

(let ((a 4))
  (eval `(lambda () ,x)))

그러나이 두 가지 모두 문제가 발생합니다. Eval은 최상위 수준에서 코드를 평가하므로 표현식에 포함 된 변수를 캡처 할 수 없습니다. Eval에 LET 양식을 넣을 수는 없습니다. 해결책이 있습니까?

편집 : 평가 문제에 대한 해결책이 없다면 어떻게 할 수 있습니까?

편집 : 정확히 무엇을 시도하는지에 대한 질문이있었습니다. 컴파일러를 쓰고 있습니다. 표현이 정의 된 어휘 환경에서 변수가 닫힌 S- 표현을 받아들이고 싶습니다. 매크로로 쓰는 것이 실제로 더 낫습니다.

도움이 되었습니까?

해결책

필요한 바인딩이있는 코드를 만들어야합니다. 코드 주위를 랩하고 코드에서 사용할 수 있도록하려는 모든 변수를 바인딩하십시오.

(defvar *x* '(+ a 2))

(let ((a 4))
  (eval `(let ((a ,a))
           ,*x*)))

다른 팁

CLISP는 어휘 환경에서 양식을 평가하기위한 확장을 구현합니다. 그것이 확장이라는 사실에서, 나는 당신이 표준 준수 방식으로 그렇게 할 수 없다고 생각합니다.

(ext:eval-env x (ext:the-environment))

보다 http://clisp.cons.org/impnotes.html#eval-environ.

해결하려는 실제 문제는 무엇입니까? 아마도 당신은 그것을 잘못된 방식으로 해결하려고 노력하고 있습니다. 어휘 바인딩은 외부에서 얻는 임의의 물건이 아니라 범위 내에서 어휘적으로 나타나는 것들을위한 것입니다.

동적 폐쇄를 원하십니까? 그런 것은 공통 LISP에는 존재하지 않지만 일부 LISP 방언 (내가 이해하는 한 Pico LISP와 같은)에서는 존재하지 않습니다.

당신은 주목하십시오 ~할 수 있다 다음을 수행하십시오.

(defvar *a*)
(defvar *x* '(+ *a* 2))  ;'

(let ((a 10))
  ;; ...
  (let ((*a* a))
    (eval *x*)))

그래도 당신이 정말로 이것을 원하는지 여부에 대해 열심히 생각하는 것이 좋습니다.

일반적인 LISP에서는 정의 할 수 있습니다 *Evalhook* 환경을 전달할 수 있습니다 (eval ...). *evalhook* 플랫폼 독립적입니다.

Compile을 사용하여 표현식을 함수로 컴파일 한 다음 ProGV를 사용하여 변수가 동적으로 설정된 환경에서 컴파일 된 기능을 기능 할 수 있습니다. 또는 더 나은 Compile을 사용하여 변수를 수락하는 기능으로 표현식을 컴파일하십시오.

컴파일은 함수 정의를 목록으로 받아들이고 기능으로 바꿉니다. SBCL의 경우이 기능은 기계 코드로 컴파일되며 효율적으로 실행됩니다.

첫 번째 옵션 (Compile 및 Progv 사용) :

(defvar *fn* (compile nil '(lambda () (+ a 2)))
(progv '(a) '(4) (funcall *fn*))
=>
6

두 번째 옵션 :

(defvar *fn* (compile nil '(lambda (a) (+ a 2))))
(funcall *fn* 4)
=>
6
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top