2013-05-30 46 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>)