They are only the same within the same backqoute:
user=> `(o# o# o#)
(o__2127 o__2127 o__2127)
There they're all the same.
user=> `(o# o# ~`(o# o#) o#)
(o__2151 o__2151 (o__2150 o__2150) o__2151)
In that example, the inner backqoute gives different values.
Instead you may have to use (gensym) manually. ...or rewrite your
macro to use a single backquote expression:
(defmacro in [obj & choices]
`(some #{~obj} (list ~@choices)))
--Chouser
That is equivalent to the following:
user=> (get #{1} 1)
1
user=> (get #{2} 1)
nil
Sets can act as functions of their elements (see bottom of http://clojure.org/data_structures)
.
The same thing works with maps:
user=> ({"1" 1} "1")
1
user=> ({"1" 1} "2")
nil
It may look strange at first, but it is convenient. Stranger still is
that you can use a keyword (or symbol) as a function and the set as
the argument:
user=> (:a #{:a})
:a
user=> (:b #{:a})
(:b #{:a})
nil
Again, the same thing works with maps:
user=> (:a {:a "a"})
(:a {:a "a"})
"a"
user=> (:b {:a "a"})
nil
Moxley
Apart from the pedantic value in making it work, why would one want this
functionality in a macro rather than a plain old function?
Randall Schulz
> Which is somewhat correct but the problem is its not a
> short circuited evaluation like 'or', so the second
> and third tests are also done.
Here's another way that does short circuit:
user=> (defn in3 [obj & items] (some #(= % obj) items))
#'user/in3
user=> (in3 'a 'c 'd 'e)
nil
user=> (in3 'a 'c 'd 'a)
true
user=>
You would need a macro if you wanted to delay evaluation of the "items".
--Steve
You could use:
(first (filter identity (map ...)))
which will return the first 'true' in the map, or nil if none is
found. Since filter and map are both lazy, only the needed tests are
performed.
It's still not short-circuiting, though, if your sequence is strict.
In your example, "choices" is a sequence over an array, meaning that
all the values in "choices" have all been evaluated before the (map)
call.
> Clojure seems to be having a lot of cool utility methods
> that we normally end up writing and putting in a utils.lisp.
Agreed!
Graham