secd in clojure
clojure でも secd machine を書いてみようとやってみて、あまりに clojure について知らなすぎることが分かった。
- (cons 1 2) はエラー。(cons 1 (list 2)) は OK
- car, cdr はfirst,rest
- begin, progn のかわりに do
- cond,let は lisp に比べてカッコが一つ少ない。
- clojure-mode.el (ちょっと古いかもしれないが)は、C-c C-l (clojure-load-file) でいちいち repl バッファをポップアップする。バッファを分割してソースと repl にしておくと、C-c C-l で両方が repl バッファになってしまう。うっとうしいので closure-load-file 関数の switch-to-lisp をとりあえずコメントアウトした。
まだ途中だけど一応張っておく。
(defn car [lst] (first lst)) (defn cdr [lst] (rest lst)) (defn cadr [lst] (car (cdr lst))) (defn cddr [lst] (cdr (cdr lst))) (defn locate [i j env] (nth (nth env (- i 1)) (- j 1))) (defn secd "SECD Machine" [s e c d] (if (empty? c) (list s e c d) (let [c0 (first c) cs (rest c)] (println (list s e c d)) (cond ;; A. Push Objects to Stack (= c0 'NIL) (recur (cons 'NIL s) e cs d) (= c0 'LDC) (recur (cons (cadr c) s) e (rest cs) d) ;;(= c0 'LD) (recur (cons (locate i j e) s) e (rest c d) ;; B. Built-in Functions ;; Unary operator OP: (= c0 '+) (recur (cons (+ (car s) (cadr s)) (cddr s)) e cs d) (= c0 '-) (recur (cons (- (car s) (cadr s)) (cddr s)) e cs d) ;; C. The Special function IF_THEN_ELSE (= c0 'SEL) (do (if (car s) (recur (cdr s) e (car cs) (cons (cddr cs) d)) (recur (cdr s) e (cadr cs) (cons (cddr cs) d)))) :else (recur s e cs d)))))
多分続く。