[英]Java style FOR loop in a clojure interpeter?
我有clojure的基本口譯員。 現在我需要實施
for (initialisation; finish-test; loop-update) {
statements
}
在我的翻譯中。 我將附上我到目前為止得到的解釋器代碼。 任何幫助表示贊賞。
口譯員
(declare interpret make-env) ;;
(def do-trace false) ;;
;; simple utilities
(def third ; return third item in a list
(fn [a-list]
(second (rest a-list))))
(def fourth ; return fourth item in a list
(fn [a-list]
(third (rest a-list))))
(def run ; make it easy to test the interpreter
(fn [e]
(println "Processing: " e)
(println "=> " (interpret e (make-env)))))
;; for the environment
(def make-env
(fn []
'()))
(def add-var
(fn [env var val]
(cons (list var val) env)))
(def lookup-var
(fn [env var]
(cond (empty? env) 'error
(= (first (first env)) var) (second (first env))
:else (lookup-var (rest env) var))))
;; -- define numbers
(def is-number?
(fn [expn]
(number? expn)))
(def interpret-number
(fn [expn env]
expn))
;; -- define symbols
(def is-symbol?
(fn [expn]
(symbol? expn)))
(def interpret-symbol
(fn [expn env]
(lookup-var env expn)))
;; -- define boolean
(def is-boolean?
(fn [expn]
(or
(= expn 'true)
(= expn 'false))))
(def interpret-boolean
(fn [expn env]
expn))
;; -- define functions
(def is-function?
(fn [expn]
(and
(list? expn)
(= 3 (count expn))
(= 'lambda (first expn)))))
(def interpret-function
(fn [expn env]
expn))
;; -- define addition
(def is-plus?
(fn [expn]
(and
(list? expn)
(= 3 (count expn))
(= '+ (first expn)))))
(def interpret-plus
(fn [expn env]
(+
(interpret (second expn) env)
(interpret (third expn) env))))
;; -- define subtraction
(def is-minus?
(fn [expn]
(and
(list? expn)
(= 3 (count expn))
(= '- (first expn)))))
(def interpret-minus
(fn [expn env]
(-
(interpret (second expn) env)
(interpret (third expn) env))))
;; -- define multiplication
(def is-times?
(fn [expn]
(and
(list? expn)
(= 3 (count expn))
(= '* (first expn)))))
(def interpret-times
(fn [expn env]
(*
(interpret (second expn) env)
(interpret (third expn) env))))
;; -- define division
(def is-divides?
(fn [expn]
(and
(list? expn)
(= 3 (count expn))
(= '/ (first expn)))))
(def interpret-divides
(fn [expn env]
(/
(interpret (second expn) env)
(interpret (third expn) env))))
;; -- define equals test
(def is-equals?
(fn [expn]
(and
(list? expn)
(= 3 (count expn))
(= '= (first expn)))))
(def interpret-equals
(fn [expn env]
(=
(interpret (second expn) env)
(interpret (third expn) env))))
;; -- define greater-than test
(def is-greater-than?
(fn [expn]
(and
(list? expn)
(= 3 (count expn))
(= '> (first expn)))))
(def interpret-greater-than
(fn [expn env]
(>
(interpret (second expn) env)
(interpret (third expn) env))))
;; -- define not
(def is-not?
(fn [expn]
(and
(list? expn)
(= 2 (count expn))
(= 'not (first expn)))))
(def interpret-not
(fn [expn env]
(not
(interpret (second expn) env))))
;; -- define or
(def is-or?
(fn [expn]
(and
(list? expn)
(= 3 (count expn))
(= 'or (first expn)))))
(def interpret-or
(fn [expn env]
(or
(interpret (second expn) env)
(interpret (third expn) env))))
;; -- define and
(def is-and?
(fn [expn]
(and
(list? expn)
(= 3 (count expn))
(= 'and (first expn)))))
(def interpret-and
(fn [expn env]
(and
(interpret (second expn) env)
(interpret (third expn) env))))
;; -- define with
(def is-with?
(fn [expn]
(and
(list? expn)
(= 3 (count expn))
(= 'with (first expn)))))
(def interpret-with
(fn [expn env]
(interpret (third expn)
(add-var env
(first (second expn))
(interpret (second (second expn)) env)))))
;; -- define if
(def is-if?
(fn [expn]
(and
(list? expn)
(= 4 (count expn))
(= 'if (first expn)))))
(def interpret-if
(fn [expn env]
(cond (interpret (second expn) env) (interpret (third expn) env)
:else (interpret (fourth expn) env))))
;; -- define function-application
(def is-function-application?
(fn [expn env]
(and
(list? expn)
(= 2 (count expn))
(is-function? (interpret (first expn) env)))))
(def interpret-function-application
(fn [expn env]
(let [function (interpret (first expn) env)]
(interpret (third function)
(add-var env
(first (second function))
(interpret (second expn) env))))))
;; 口譯員本身
(def interpret
(fn [expn env]
(cond do-trace (println "Interpret is processing: " expn))
(cond
; basic values
(is-number? expn) (interpret-number expn env)
(is-symbol? expn) (interpret-symbol expn env)
(is-boolean? expn) (interpret-boolean expn env)
(is-function? expn) (interpret-function expn env)
; built-in functions
(is-plus? expn) (interpret-plus expn env)
(is-minus? expn) (interpret-minus expn env)
(is-times? expn) (interpret-times expn env)
(is-divides? expn) (interpret-divides expn env)
(is-equals? expn) (interpret-equals expn env)
(is-greater-than? expn) (interpret-greater-than expn env)
(is-not? expn) (interpret-not expn env)
(is-or? expn) (interpret-or expn env)
(is-and? expn) (interpret-and expn env)
; special syntax
(is-with? expn) (interpret-with expn env)
(is-if? expn) (interpret-if expn env)
; functions
(is-function-application? expn env) (interpret-function-application expn env)
:else 'error)))
您可能已經發現,clojure沒有for(盡管您可以實現)循環。 您只需要使用一個簡單的遞歸調用,如下所示:
(loop [var inital-value]
;; statements (regarding "var")
(when-not finish-test
(recur update-var)))
只要您的finish-test
計算結果為false
, recur
就會使用update-var
的值作為新var
將執行返回到loop
的開始。 參見http://clojure.org/functional_programming
我不確定您所解釋的語言的語法是什么,但是看起來您已經實現了lambda
,這是獲取大量語法糖所真正需要的。 您可以使用lambda
實現類似for
循環的功能。
您真正需要做的就是添加一個for-handler
函數,該函數可以解析如下表達式:
(for (i 0 (< 1 10))
(print i))
變成:
((lambda ()
(define (loop i n)
(if (or (< i n) (= i n))
(begin (print i) (loop (+ 1 i) n))))
(loop 1 10)))
然后傳遞此新表達式再次進行interpret
。 上面的代碼來自我的解決方案到SICP練習4.9
我沒有花太多時間試圖弄清楚您的解釋器是否支持這樣的內部定義,但是您似乎可以with
它來執行以下操作:
(with (loop (lambda (i n)
(if (or (< i n) (= i n))
(begin (print i) (loop (+ 1 i) n))))
(loop 1 10))
本質上,您需要在遞歸函數的應用程序中擴展for
表達式。 上面的代碼定義了一個名為loop
的函數,並立即調用它。 外層lambda
迫使整個表達式立即運行。
如果您想了解更多詳細信息,請參閱優秀的《計算機程序的結構和解釋》一章,以構建元圓解釋器,並討論實現內部定義以及它們所謂的“派生表達式”,這基本上是糖一樣for
。
祝好運!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.