Reputation: 32715
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
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
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
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