2016-10-19 70 views
0

對於一個大學項目,我們正在研究學習計劃,但是我們已經被投入了一個幾乎沒有知識的艱鉅任務。我們給了某些函數,如「let」,「cond」,「and'」等,並要求添加宏。在計劃中添加宏

(define eval 
    (λ (e env) 
    (cond ((symbol? e) (lookup-var e env)) 
      ((not (list? e)) e) ; non-list non-symbol is self evaluatory 
      ;; special forms go here: 
      ((equal? (car e) 'λ)  ; (λ VARS BODY) 
      (let ((vars (cadr e)) (body (caddr e))) 
      (list '%closure vars body env))) 
      ((equal? (car e) 'if) 
      (eval_ (if (eval_ (cadr e) env) (caddr e) (cadddr e)) env)) 
      ((equal? (car e) 'quote) (cadr e)) 
      ;; Add More Macros Here: 
      ;; ((equal? (car e) 'let) xxx) 
      ;;((equal? (car e) 'cond) xxx) 
      ;;((equal? (car e) 'and) xxx) 
      ;((equal? (car e) 'or) xxx) 
      (else (let ((eeoe (map (λ (e0) (eval_ e0 env)) e))) 
        (apply_ (car eeoe) (cdr eeoe))))))) 

所以基本上我們被要求填寫空格,';;'評論是。 我試着做了「COND一部分,並得到這個

((equal? (car e) 'cond) 
      (env (cdr e) env)) 

但我不知道,如果它是正確的(方案不甚瞭解)。任何幫助解決這個問題將非常感激。謝謝。

回答

1

這不是真正的宏,而是你添加的特殊形式。如果你知道let只是匿名函數調用的語法糖。例如。

((lambda (a b) body ...) expr1 expr2) 

,讓你去let是這樣工作的:

(let ((bindings (cadr e)) 
     (body (cddr e))) 
    (eval_ `((lambda ,(map car bindings) ,@body) ,@(map cadr bindings)))) 

現在真正的宏,你將引入一個新的,如果你改變你評估器已經和評估

(let ((a expr1) (b expr2)) body ...) 

支持%closure的類型,以便每當你找到它作爲運算符時,你都綁定符號而不是它們的評估,運行評估程序就好像它是函數一樣,然後執行_eval的結果。然後,而不是實施condlet你可以添加一個函數,如何將它重寫到你已經支持的東西。這樣,就可以使let這樣的:

((lambda (let) 
    (let ((a expr1) (b expr2)) 
    (cons a b))) 
    (~ (bindings . body) `((lambda ,(map car bindings) ,@body) ,@(map cadr bindings)))) 

假定您quasiquote和map,但它可以很容易在沒有這些有更詳細的代碼實現。 ~只是隨機選擇爲λ的宏版本。評估時,它可能會構成一個%mclosure結構,您需要專門處理它以不評估其參數,但疏忽結果。從此,您可以通過在引導環境中預定義%mclosure來支持特殊窗體。