来自 clojure.java.api.Clojure 的意外行为



我一直在尝试Clojure 1.6.0中引入clojure.java.api,因为我想将一些Clojure功能导入我的Java项目。不幸的是,当我从 Java 调用条件函数and 或 时,它的行为并不像我预期的那样。

IFn and = Clojure.var("clojure.core", "and");
IFn or = Clojure.var("clojure.core", "or");
-- equivalent to (and true false) in clojure
and.invoke(true,false); --> returns true rather than false???   
-- equivalent to (or true false) in clojure
or.invoke(true,false); --> returns null rather than true???
-- equivalent to (and true true) in clojure
and.invoke(true,true); --> returns true as expected
-- equivalent to (or true true) in clojure    
or.invoke(true,true); --> returns null rather than true???

我不敢相信这是一个错误,所以我怀疑我错过了一些与 API 相关的相当基本的东西。不管是什么原因,它都让我相当困惑。如果有人能提供解释,我将不胜感激。

谢谢

马 特。

andor是宏,它们的评估规则有些不同。例如,在 Clojure REPL 上时,尝试评估and抛出CompilerException java.lang.RuntimeException: Can't take value of a macro: #'clojure.core/and, compiling:(NO_SOURCE_PATH:0:0) .

不过应该有一种方法可以通过clojure.java.api.Clojure使用它们,但我现在还没有弄清楚,因为需要编译宏才能工作。

我能想到的下一个最佳选择是使用eval但我不确定这是你想做的事情。另一方面,当存在好的旧&&/|| Java 运算符时,为什么要使用 and/or

andor是宏,不是函数。他们期望两种或多种形式(所以clojure.lang.IPersistent符号列表或嵌套的IPersistentLists,我认为),他们将其扩展为let*if的组合。

(clojure.walk/macroexpand-all '(and true false))
;returns:
(let* [and__3941__auto__ true] 
      (if and__3941__auto__ 
        false
        and__3941__auto__))

最好做一个代表你使用andor的clojure fn。例如,要将它们接管集合:

(defn reduce-and [values]
  (reduce #(and %1 %2) values))
(defn reduce-or [values]
  (reduce #(or %1 %2) values))

最新更新