I\'m taking a look at the excellent Clojure tutorial here. In one of the examples it has Clojure code along the following lines:
(def vowel? (set \"aeiou\"))
Aha! I ended up finding it out myself. It doesn't actually return true
or false
, rather it returns the first occurrence in the set, or nil if it doesn't occur.
And because you can use this as a condition (nil being handled as false, and non-nil as true), this works as a nice little hack for checking if a string contains a letter.
(vowel? (first "abc")) ; => "a"
(vowel? (first "cba")) ; => nil
(if (vowel? (first "abc"))
(println "yay")
(println "oops")) ; => "yay"
This is perfectly analogous to how maps (the most natural objects in Clojure) work. When the map is called as a function, it works as a mapping:
user=> (def ob {:foo "bar", :bar :baz, :qwerty 42})
#'user/ob
user=> (ob :foo)
"bar"
So it makes sense that a Clojure set can be called as a function, and will work as a membership test. By the way, if you use keywords (those things that start with a colon) as the keys of a mapping, they also work as similar functions, so you can do
user=> (:bar ob)
:baz
and even the same thing with sets of keywords:
user=> (def vowel-keywords (set [:a :e :i :o :u]))
#'user/vowel-keywords
user=> (:a vowel-keywords)
:a
user=> (:b vowel-keywords)
nil
But, again, this latter trick only works with keywords, not anything else that you might use as keys in a mapping or members in a set.