clojure.java.api.clojure的意外行为
我一直在试验clojure 1.6.0中引入的clojure.java.api.clojure的意外行为,java,api,clojure,conditional,Java,Api,Clojure,Conditional,我一直在试验clojure 1.6.0中引入的clojure.java.api,因为我想将一些clojure功能导入到我的java项目中。不幸的是,当我从Java调用条件函数和和或时,它的行为与我预期的不同 IFn and = Clojure.var("clojure.core", "and"); IFn or = Clojure.var("clojure.core", "or"); -- equivalent to (and true false) in clojure and.invoke
clojure.java.api
,因为我想将一些clojure功能导入到我的java项目中。不幸的是,当我从Java调用条件函数和和或时,它的行为与我预期的不同
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???
我不敢相信这是一个bug,所以我怀疑我遗漏了一些与API相关的基本信息。不管是什么原因,这让我很困惑。如果有人能给我一个解释,我将不胜感激
谢谢
Matt.
和
和或
都是宏,它们的计算规则有些不同。例如,在Clojure REPL上,尝试计算和时抛出CompilerException java.lang.RuntimeException:无法获取宏的值:#'Clojure.core/和编译:(无源代码路径:0:0)
虽然应该有一种通过clojure.java.api.clojure
使用它们的方法,但我现在还没有弄明白,因为宏需要编译才能工作
我能想到的下一个最好的选择是使用eval
,但我不确定您是否希望这样做。另一方面,为什么要使用和/或,而旧的&
/|
Java操作符存在?和和或
都是宏,而不是函数。他们希望有两种或两种以上的形式(我认为是clojure.lang.IPersistentList或嵌套的IPersistentList),并将其扩展为let*
和if
的组合
(clojure.walk/macroexpand-all '(and true false))
;returns:
(let* [and__3941__auto__ true]
(if and__3941__auto__
false
and__3941__auto__))
您最好制作一个clojure fn,它代表您使用和和或。例如,要将它们接管集合,请执行以下操作:
(defn reduce-and [values]
(reduce #(and %1 %2) values))
(defn reduce-or [values]
(reduce #(or %1 %2) values))
考虑到减少和
和减少或
失去了原始或和和
的短路语义,这是您有时依赖的。