David J.
David J.

Reputation: 32715

Idiomatic `and` & `or` functions (not macros) in Clojure

Strange as it may sound, I am looking for function versions of the and and or macros in Clojure.

Why? For one I am curious.

Second, I want to use or in precondition and postcondition checks. This does not work:

(defn victor
  [x]
  {:post (or (nil? %) (vector %))}
  ;; ...
  )

I want the postcondition to check to see if victor returns a vector or nil, but it fails:

#<CompilerException java.lang.RuntimeException: Can't take value of a macro: #'clojure.core/or, compiling:(test/test.clj:10:1)>

I don't think bit-and and bit-or are quite what I'm looking for.

Update: This syntax works without an error:

(defn victor
  [x]
  {:post [(or (nil? %) (vector %))]}
  ;; ...
  )

I'm still curious if functions exist, though.

Upvotes: 1

Views: 113

Answers (3)

Mars
Mars

Reputation: 8854

I think the standard method is simply to wrap and and or in functions, e.g. (fn [x y] (or x y)). In some contexts, another function will work. For example, a note in the clojure docs for and suggests using (every? identity [true false]). some, not-every?, and not-any? can be used in a similar way.

Upvotes: 3

dsm
dsm

Reputation: 10395

@Triangle Man is right. Short-circuiting won't work, but nevertheless you can define your own function versions:

user=> (defn && [x y] (and x y))
#'user/&&
user=> (&& true false)
false
user=> (&& true true)
true
user=> (defn || [x y] (or x y))
#'user/||
user=> (|| true false)
true
user=> (|| true true)
true
user=> (|| false false)
false
user=> 

Upvotes: 1

John Sullivan
John Sullivan

Reputation: 1311

In general, and and or functions would be undesirable because they cannot use short-circuiting. Consider the following code:

(and false some-expensive-fn)
(or true some-expensive-fn)

With and and or as macros the above code won't execute some-expensive-fn, because it is unnecessary to determine the overall truth value of the expression. In function expressions the arguments are evaluated before being passed to the function, but in macros they are not.

Upvotes: 3

Related Questions