2013-05-30 44 views
3

我正试图学习计划,并试图在计划中实现let *的解释器。下面是语法:如何在计划中实现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 

我已经学会了如何实现之前让,那就是:

(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))))) 

如何修改解释为让这样我可以编写一个解释为让*?谁能帮忙?

谢谢

回答

2

最近这个问题已经被多次询问过,在计划问题列表中向下滚动。这是它的要点:let*是一个语法转换,请在SICP中阅读有关此主题的更多信息,查找标题为“派生表达式”的部分。这种情况的关键思想是:一旦你的评估发现一个表达式,比如这个:

(let* ((a 10) 
     (b (+ 10 a))) 
    (+ a b)) 

...你可以直接将它转换为等效串联嵌套lambda应用程序,它可以像这样很容易评价的:

((lambda (a) 
    ((lambda (b) 
     (+ a b)) 
    (+ 10 a))) 
10) 

替代地,可以执行的中间步骤和第一变换let*成一系列嵌套let S的,然后评价它们 - 这是有用的情况下,你已经实施了let特殊形式。上述同样的例子是这样的:

(let ((a 10)) 
    (let ((b (+ 10 a))) 
    (+ a b))) 

当然,首先你必须知道如何评价一个lambda形式。这里的全部观点是,letlet*都是特殊形式(不过是语法糖),它们不遵循相同的程序应用程序的评估模型,并且需要在评估程序级别进行特殊处理 - 在此案例,这是一种语法转换,产生了我们知道如何评估的不同表达式。

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 ...))))) 
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>)