我正在尝试学习方案并试图在方案中实现let *的解释器。这是语法:
<s6> -> <expr>
| <define>
<expr> -> NUMBER | IDENT | <if> | <let> | <letstar> | <lambda> | <application>
<define> -> ( define IDENT <expr> )
<if> -> ( if <expr> <expr> <expr> )
<let> -> ( let ( <var_binding_list> ) <expr> )
<letstar> -> ( let* ( <var_binding_list> ) <expr> )
<lambda> -> ( lambda ( <formal_list> ) <expr> )
<application> -> ( <operator> <operand_list> )
<operator> -> <built_in_operator> | <lambda> | IDENT
<built_in_operator> -> + | * | - | /
<operand_list> -> <expr> <operand_list> | empty
<var_binding_list> -> ( IDENT <expr> ) <var_binding_list> | ( IDENT <expr> )
<formal_list> -> IDENT <formal_list> | IDENT
我已经学会了如何实现let,这里是:
(define let-stmt? (lambda (e)
(and (list? e) (equal? (car e) 'let) (= (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 s6-interpret (lambda (e env) //thanks to GoZooner
(cond
((number? e) e)
((symbol? e) (get-value e env))
((not (list? e)) (error "s6-interpret: cannot evaluate -->" e))
((let-stmt? e)
(let ((names (map car (cadr e)))
(inits (map cadr (cadr e))))
(let ((vals (map (lambda (init) (s6-interpret init env)) inits)))
(let ((new-env (append (map cons names vals) env)))
(s6-interpret (caddr e) new-env)))))
如何修改解释器以便我可以为let *编写解释器?有人可以帮忙吗?
由于
答案 0 :(得分:2)
最近已多次询问此问题,向下滚动计划问题列表。以下是它的要点:let*
是一种语法转换,在SICP中阅读更多有关此主题的内容,查找标题为“派生表达式”的部分。这种情况的关键思想是,只要你的评估者找到一个如下表达式:
(let* ((a 10)
(b (+ 10 a)))
(+ a b))
...您可以直接将其转换为等效的嵌套lambda
应用程序系列,可以像这样轻松地进行评估:
((lambda (a)
((lambda (b)
(+ a b))
(+ 10 a)))
10)
或者,您可以执行一个中间步骤,然后首先将let*
转换为一系列嵌套的let
,然后对它们进行评估 - 如果您已经实现了{{1},这非常有用特殊形式。上面的例子如下:
let
当然,首先您必须知道如何评估(let ((a 10))
(let ((b (+ 10 a)))
(+ a b)))
表单。这里的重点是,lambda
和let
都是特殊形式(仅仅是语法糖),它们不遵循相同的评估模型,比如程序应用程序,需要一个特殊的评估者层面的处理 - 在这种情况下,是一种语法转换,它产生一种我们知道如何评估的不同表达。
答案 1 :(得分:1)
来自R5RS,第7.3节:
(define-syntax let*
(syntax-rules ()
((let* () body1 body2 ...)
(let () body1 body2 ...))
((let* ((name1 val1) (name2 val2) ...) body1 body2 ...)
(let ((name1 val1))
(let* ((name2 val2) ...)
body1 body2 ...)))))
答案 2 :(得分:1)
知道:
(let* ((a ...) (b ...) (c ...)) body ...)
相当于:
(let ((a ...))
(let ((b ...))
(let ((c ...))
body ...)))
(参见R5RS,第44页,(define-syntax let* ...)
)。现在,鉴于此,并且知道:
(let ((a ...)) body ...)
相当于:
((lambda (a) body ...) ...)
我上面展示的let*
的“扩展”变为:
((lambda (a)
((lambda (b)
((lambda (c)
body ...)
<c-init>))
<b-init>))
<a-init>)