简体   繁体   English

Java风格的FOR循环在clojure交错器中?

[英]Java style FOR loop in a clojure interpeter?

I have a basic interpreter in clojure. 我有clojure的基本口译员。 Now i need to implement 现在我需要实施

for (initialisation; finish-test; loop-update) {
statements
}  

inside my interpreter. 在我的翻译中。 I will attach my interpreter code I got so far. 我将附上我到目前为止得到的解释器代码。 Any help is appreciated. 任何帮助表示赞赏。

Interpreter 口译员

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

;; ;; the interpreter itself 口译员本身

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

As you may have found, clojure doesn't have for (though you could implement one) loops. 您可能已经发现,clojure没有for(尽管您可以实现)循环。 You just use a simple recursive call like this: 您只需要使用一个简单的递归调用,如下所示:

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

As long as your finish-test evaluates to false , recur will return execution to the start of loop using the value of update-var as the new var . 只要您的finish-test计算结果为falserecur就会使用update-var的值作为新var将执行返回到loop的开始。 See http://clojure.org/functional_programming 参见http://clojure.org/functional_programming

I wasn't completely sure what the syntax of your interpreted language is, but it looks like you've implemented lambda which is all you really need to get a lot of syntactic sugar. 我不确定您所解释的语言的语法是什么,但是看起来您已经实现了lambda ,这是获取大量语法糖所真正需要的。 You can implement things like for loops using lambda . 您可以使用lambda实现类似for循环的功能。

All you really need to do is add a for-handler function which parses an expression like: 您真正需要做的就是添加一个for-handler函数,该函数可以解析如下表达式:

(for (i 0 (< 1 10))
  (print i))

into: 变成:

((lambda ()
   (define (loop i n)
             (if (or (< i n) (= i n))
                 (begin (print i) (loop (+ 1 i) n))))
   (loop 1 10)))

and then passes this new expression to interpret again. 然后传递此新表达式再次进行interpret The code above is from my solution to the SICP Exercise 4.9 上面的代码来自我的解决方案到SICP练习4.9

I didn't spend too much time trying to figure out if your interpreter supports internal defines like this, but it looks like you have with which may allow you to do something like this: 我没有花太多时间试图弄清楚您的解释器是否支持这样的内部定义,但是您似乎可以with它来执行以下操作:

   (with (loop (lambda (i n)
                 (if (or (< i n) (= i n))
                     (begin (print i) (loop (+ 1 i) n))))
         (loop 1 10))

Essentially, you need to expand the for expression in an application of a recursive function. 本质上,您需要在递归函数的应用程序中扩展for表达式。 The above code defines a function named loop and immediately calls it. 上面的代码定义了一个名为loop的函数,并立即调用它。 The outer lambda forces the entire expression to run right away. 外层lambda迫使整个表达式立即运行。

If you want some more details on this, there is a chapter in the excellent Structure and Interpretation of Computer Programs on building metacircular interpreters, and there are discussions on implementing internal definitions, as well as discussions what they call "derived expressions" which is basically sugar like for . 如果您想了解更多详细信息,请参阅优秀的《计算机程序的结构和解释》一章,以构建元圆解释器,并讨论实现内部定义以及它们所谓的“派生表达式”,这基本上是糖一样for

Good luck! 祝好运!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM