Unexpected behavior from clojure.java.api.Clojure

I have been experimenting with the clojure.java.api

one introduced in Clojure 1.6.0 since I would like to import some Clojure functionality into my java project. Unfortunately, it doesn't behave the way I expect it to when I call conditional functions and and or from 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???

      

I can't believe this is a bug, so I suspect I'm missing something fundamental enough API related. Whatever the reason, it left me rather confused. If anyone can suggest an explanation, I would be very grateful.

Thank,

Mt.

+3


source to share


2 answers


and

and or

are macros, and the rules for evaluation are slightly different for them. For example, when at the Clojure REPL trying to evaluate and

throws CompilerException java.lang.RuntimeException: Can't take value of a macro: #'clojure.core/and, compiling:(NO_SOURCE_PATH:0:0)

.

There must be a way to use them via clojure.java.api.Clojure

though, but I haven't figured it out yet since macros need to be compiled to work.



The next best option I can think of is using eval

, but I'm not sure if this is what you want to do. On the other hand, why use and

/ or

when the old old &&

/ ||

Java operators exist ?

+3


source


and

and or

are macros, not functions. They expect two or more forms (so clojure.lang.IPsistentList of characters or nested IPersistentLists, I think), which they expand into a combination of let*

and if

.

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

      



You might be better off doing clojure fn that uses and

and or

on your behalf. For example, to take them by collection:

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

      

+1


source







All Articles