2011-01-07 5 views
2

私はクロージャーで基本的な通訳を持っています。今私は実装する必要がありますクロージャーインターピターのJavaスタイルFORループ?

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

;;あなたが見つけているかもしれませんが、ループ(あなたは1を実装することができますが)インタプリタ自体

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

あなたは何をしようとしていますか? clojureでforループを作成するか、独自のカスタム言語のためにclojureでインタープリタを作成するには? –

+2

あなたの特定の質問に対する回答ではありませんが(それが何であるかは不明ですが)、マルチメソッドをチェックアウトしてください。彼らはあなたがそこにあるモノリシックコンディションを取り除くためにうまくいくはずです。 – Rayne

答えて

0

あなたの解釈言語の構文は完全にはわかりませんでしたが、実際に多くの構文糖を得るのに本当に必要なのはlambdaを実装したようです。 lambdaを使用してforループを実装することができます。

(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に、この新しい表現を渡し

あなたが本当にやらなければならないことは、のような式を解析しfor-handler機能を追加することです。上記のコードは、私の解決策からです。SICP Exercise 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は、式全体をすぐに実行させます。

詳細については、Structure and Interpretation of Computer Programsの中高年通訳者のための章があります。内部定義の実装や、基本的には「派生表現」と呼ばれるものについての議論がありますforのように。

幸運を祈る!

+0

Clojureでは、**ラムダ**は** fn **です。 – Markc

+0

私は知っていますが、OPの解釈言語では、キーワードは 'lambda 'です。上記のすべての展開されたコードは解釈されますが、Clojureは意味を持ちません。 – spacemanaki

0

は、Clojureのは、のために持っていません。 recurが新しいvarとしてupdate-varの値を使用してloopの先頭に実行を返します、限り、あなたのfinish-testfalseに評価される

(loop [var inital-value] 
    ;; statements (regarding "var") 
    (when-not finish-test 
    (recur update-var))) 

:あなたはこのような単純な再帰呼び出しを使用しています。 http://clojure.org/functional_programming

+1

Clojureには** **マクロ*、http://clojure.github.com/clojure/clojure.core-apiがあります。html#clojure.core/for – Markc

+1

これは、リストの理解として機能する 'for'マクロを持っています。質問者がリクエストした "JavaスタイルのFORループ"のようなものではなく、問題を混乱させたくないので、私は言及しませんでした。私が言ったのは、clojureに* forループ*がないということでした。 – Chris

関連する問題