2017-09-26 3 views
1

저는 SchemR 언어를 시험하기 위해 DrRacket 환경을 사용하고 있습니다. 궁금왜 이것이 Scheme에서 평가되지 않습니까?

(define sum+1 '(+ x y 1)) 

는 다음과 같은 식을 평가하지 않는 이유 : : 다음과 같이

나는 합계 + 1을 정의

(let ([x 1] [y 2]) (eval sum+1)) 

이렇게하면 올바른 값을 반환하는 반면 :

(define x 1) 
(define y 2) 
(eval sum+1) 
+0

이 내용은 [Racket 가이드] (https://docs.racket-lang.org/guide/eval.html)에서 비교적 잘 설명되어 있습니다. – molbdnilo

답변

0

eval는 어휘 변수가 같은 표현에서 만든 모든 않는 한에서 어휘 변수와 함께 작동하지 않습니다 eval 항상 환경의 글로벌 바인딩 최상위 일어나고로

#!r7rs 
(import (scheme base) 
     (scheme eval)) 

(define env (environment '(scheme base))) 

(let ((x 10)) 
    (eval 'x env)) ; ERROR! `x` is not defined 

당신이 생각 할 수 있습니다 두 번째 인수로 전달하십시오. 당신은 아마이 같이 당신의 어휘 환경에서 값을 전달하여 속일 수 시간으로

(eval '(let ((x 10)) 
     x) 
     env) ; ==> 10 


(let ((x 10)) 
    (eval `(let ((x ,x)) 
      x) 
     env) ; ==> 10 

대부분의 계획 구현 코드 지역 변수는 일반적으로 할당 스택되어 실행합니다.

(define (test v) 
    (display v) 
    (newline) 
    (eval 'v)) 

런타임에이로 변신 할 수 있음 :

(define (test 1 #f) ; indicates 1 argument, no rest 
    (display (ref 0)) ; fetches first argument from stack 
    (newline) 
    (eval 'v))  ; but what is v?, certainly not the first argument 

는 또한이 코너 케이스를 만들 수 있습니다 따라서 무언가가이 코드를 상상한다. 돌연변이하면 어떻게 될까요?이 v이 많은 컴파일 계획의 구현은 코드가 v 특별한 필요가 있다고 실행하기 전에 알 필요가 있으므로 다른 돌연변이 변수를 처리 할 필요가 돌연변이 도착하지 명백한 것을 그래서

(define (test v) 
    (eval '(set! v 10)) 
    v) 

eval에 대한 구조는 사용자의 입력에서 올 수도 (set! v 10)은 데이터베이스 또는 사용자 입력에서 올 수 있으므로 결정할 수는 없습니다. 따라서 로컬 바인딩을 포함시키지 않으면 많은 문제를 해결할 수 있으며 언어를 최적화하고 컴파일하기가 더 쉽습니다.

매크로를 퍼스트 클래스 객체로 전달할 수 있기 때문에 해석 할 수있는 리스프 언어가 있습니다. 이러한 언어는 컴파일 할 때 추론 할 수 없습니다.

0

let의 명령이 작동하지 않는 이유는 let로컬 변수을 만듭니다. 즉, 생성 된 변수는 어디서나 액세스 할 수 없으며 let의 본문 인수 내에서만 액세스 할 수 있습니다. 당신의 예에서

, 당신은 정의 : xyeval 문에 정의되기 때문에

(let ([x 1] [y 2]) (eval sum+1)) 

이 아닌 내에서 작동하지 않습니다

(define sum+1 '(+ x y 1)) 

그런 다음 당신이 명령 절차 sum+1. 이것은 반 직관적으로 보일 수 있지만 다른 입력과 함께 많은 오류를 예방합니다.

두 번째 예는 있었다 :

(define x 1) 
(define y 2) 
(eval sum+1) 

xy 때문에 전 세계적으로을 작품 정의 않습니다. 즉, 어디서나 액세스 할 수 있습니다. 그런 다음 정의가 sum+1에 적용되고 인쇄 할 수 있습니다. 질문이나 피드백이 있으면 회신 해주십시오!

+0

답변을 많이 주셔서 감사합니다. 그래서 'eval'은 호출 된 범위의 정의를 볼 수 없으며 전역 범위의 정의 만 볼 수 있습니다. 다른 프로 시저가 전역 프로 시저를 오버라이드하는 로컬 스코프에 액세스 할 수 있기 때문에이 동작이 이상하다는 것을 알았습니다. 그리고 eval 자체가 프로 시저이고 다른 프로 시저처럼 작동해야하는 특수한 폼이 아니기 때문에! 이 행동을 정당화하는 이유가 있습니까? –

+0

eval이 다른 프로 시저처럼 작동하지 않는 이유에 대해 확신 할 수 없지만 여기에 내 생각에 최선의 추측이 있습니다. eval은 평가할 항목을 묻는 특정 함수이므로 다른 함수와 마찬가지로), "이 문제를 해결하기 위해 어떤 정보가 있습니까?" 이 문제를 해결하기 위해 나에게 어떤 정보가 주어 졌습니까? "라고 묻습니다. 즉, 전 세계적으로 불리는 절차와는 대조적으로 특정한 지침이 필요합니다. (유감스럽게 생각하지 않으면 유감스럽게 생각합니다.) –

+1

'eval' *이 어휘 바인딩을 볼 수있는 구현 방법을 생각해 볼 가치가 있습니다 : 특히 어떻게해야할까요? (eval 읽기))'직장? 컴파일러는 어떻게 작동합니까? – tfb

관련 문제