我正在尝试为方案编写解释器。到目前为止,我实现了define,if和一些算术表达式。这是我的翻译的语法:
<s6> -> <expr>
| <define>
<expr> -> NUMBER
| IDENT
| <if>
| <let>
<define> -> ( define IDENT <expr> )
<if> -> ( if <expr> <expr> <expr> )
<let> -> ( let ( <var_binding_list> ) <expr> )
<var_binding_list> -> ( IDENT <expr> ) <var_binding_list>
| ( IDENT <expr> )
这是我到目前为止编写的代码:
(define get-operator (lambda (op-symbol)
(cond
((equal? op-symbol '+) +)
((equal? op-symbol '-) -)
((equal? op-symbol '*) *)
((equal? op-symbol '/) /)
(else (error "s6-interpret: operator not implemented -->" op-symbol)))))
(define let-stmt? (lambda (e)
(and (list? e) (equal? (car e) 'let) (= (length e) 3))))
(define if-stmt? (lambda (e)
(and (list? e) (equal? (car e) 'if) (= (length e) 4))))
(define define-stmt? (lambda (e)
(and (list? e) (equal? (car e) 'define) (symbol? (cadr e)) (= (length e) 3))))
(define get-value (lambda (var env)
(cond
((null? env) (error "s6-interpret: unbound variable -->" var))
((equal? (caar env) var) (cdar env))
(else (get-value var (cdr env))))))
(define extend-env (lambda (var val old-env)
(cons (cons var val) old-env)))
(define repl (lambda (env)
(let* (
(dummy1 (display "cs305> "))
(expr (read))
(new-env (if (define-stmt? expr)
(extend-env (cadr expr) (s6-interpret (caddr expr) env) env)env))
(val (if (define-stmt? expr)
(cadr expr)
(s6-interpret expr env)))
(dummy2 (display "cs305: "))
(dummy3 (display val))
(dummy4 (newline))
(dummy4 (newline)))
(repl new-env))))
(define s6-interpret (lambda (e env)
(cond
((number? e) e)
((symbol? e) (get-value e env))
((not (list? e)) (error "s6-interpret: cannot evaluate -->" e))
((if-stmt? e) (if (eq? (cadr e) 0) ( s6-interpret (cadddr e) env) ( s6-interpret(caddr e) env)))
((let-stmt? e) (apply let (map s6-interpret (cdr e))))
(else
(let ((operands (map s6-interpret (cdr e) (make-list (length (cdr e)) env)))
(operator (get-operator (car e))))
(apply operator operands))))))
(define cs305-interpreter (lambda () (repl '())))
我写的所有东西,除了“让”工作正常。让-stmt是?程序也可以按我的意思工作,但是代码的一部分((let-stmt?e)(应用let(map s6-interpret(cdr e))))在s6-interpre中不能正常工作,它给我一个错误说“语法关键字不能用作表达”。任何人都可以帮我解释语法中给出的“let”语句的解释器吗?
谢谢
答案 0 :(得分:4)
您不能apply
特殊格式let
。错误很明显:它不是一个过程,它是语法(宏)。一种可能的解决方案是在评估者级别实现语法转换,一旦检测到let
,将其转换为lambda
表达式并对其进行评估。
查看SICP中的练习4.6,查找主题“派生表达式”。这里的关键思想是,如果你找到一个像这样的表达式:
(let ((x 1)
(y 2))
(+ x y))
您必须将其转换为可以轻松评估的表达式:
((lambda (x y)
(+ x y))
1 2)
答案 1 :(得分:1)
很容易实现let
而不用担心lambda
因为let
只是扩展环境并在新扩展的环境中评估正文。如此:
...
((let-stmt? e)
(let ((names (map car (cadr e)))
(inits (map cadr (cadr e))))
;; Evaluate inits in env
(let ((vals (map (lambda (init) (s6-interpret init env)) inits)))
;; Extend env with names+vals
(let ((new-env (append (map cons names vals) env)))
;; Eval body in new env
(s6-interpret (caddr e) new-env))))) ; assumes 'body' is one form...
...
使用这种方法也可以避免担心一般函数调用。