如何在方案中实现let *?

时间:2013-05-30 18:57:25

标签: scheme

我正在尝试学习方案并试图在方案中实现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 *编写解释器?有人可以帮忙吗?

由于

3 个答案:

答案 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))) 表单。这里的重点是,lambdalet都是特殊形式(仅仅是语法糖),它们不遵循相同的评估模型,比如程序应用程序,需要一个特殊的评估者层面的处理 - 在这种情况下,是一种语法转换,它产生一种我们知道如何评估的不同表达。

答案 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>)