1

ブール式エバリュエーター用に、次のコードをコンパイルしようとしているclojureの初心者

;core.clj
(ns my-app.core
  (:gen-class))

(defn t [& args] (if (empty? args) t
                 ((first args) t (first (rest args)))))

(defn f [& args] (if (empty? args)  f
                 ((first args)  f (first (rest args)))))

(defn | [cond1 cond2] (if (= cond1 t) t
                      (if (= cond2 t) t f)))

(defn & [cond1 cond2] (if (= cond1 f) f
                      (if (= cond2 f) f t)))

(defn ! [& args] (if (= (first args) t)
               (apply f (rest args))
               (if ( = (first args) f)
                 (apply t (rest args))
                 (! (apply (first args) (rest args))))))


(defn -main [& args]
 (loop [line (read-line)]
   (do
      (println (eval (read-string (apply str "" (interpose \space  (seq (str "(" line ")")))))))
  (if (= (count line) 1) nil (recur (read-line))))))

「leinrun」を実行して文字列「(t | t)= t」を入力するたびに、次のエラーが発生します

Exception in thread "main" java.lang.RuntimeException: Unable to resolve symbol: t in this context

ただし、「src / my_app /」ディレクトリで新しいnreplを開いて、コマンドを入力した場合

(-main)

正しい文字列と結果を取得します

( ( t | t ) = t )
true

私は注意する必要がありますleinrunを実行している間

他の文字列文字列"+1 2 3 4 5 6"は正しく評価されますが、何らかの理由で関数を認識しません(t ...)

誰かが何が起こっているのか考えがありますか?

4

1 に答える 1

3

evalの現在の(スレッドにバインドされた)値を使用して、*ns*現在「入っている」名前空間を判別します。これは、修飾されていないシンボルの解決方法を制御します。実行後のreplで(ns my-app.core ...)、あなたはmy-app.core名前空間にいるので、evalはtそこで定義したあなたを見つけます。ただし、コンパイル後、で定義tしたとしてもmy-app.core、プログラムの実行が開始されると、user名前空間にいることになり、evalはを見つけることができませんt

-mainしたがって、次のようmy-app.coreに使用して、内の名前空間をに変更するだけですbinding

(defn -main [&args]
   (binding [* ns *(the-ns'my-app.core)]
    (ループ[行(読み取り行)]
      (println(eval(read-string(apply str(interpose \ space(str "(" line ")"))))))
      (when-not(=(カウントライン)1)
        (recur(read-line)))))))
于 2013-03-26T14:46:24.130 に答える