Are there variables in Clojure sequence comprehensions?
-
04-07-2021 - |
Question
I'm reading Programming Clojure 2nd edition, and on page 49 it covers Clojure's for loop construct, which it says is actually a sequence comprehension.
The authors suggest the following code:
(defn indexed [coll] (map-indexed vector coll))
(defn index-filter [pred col]
(when pred
(for [[idx elt] (indexed col) :when (pred elt)] idx)))
(index-filter #{\a} "aba")
(0 2)
...is preferable to a Java-based imperative example, and the evidence given is that it "by using higher-order functions...the functional index-of-any avoids all need for variables."
What are "idx", "elt" if they are not variables? Do they mean variables besides the accumulators?
Also, why #{\a} instead of "a"?
La solution
There are no variables in functional languages. Actually, you need distinguish variable and value.
idx
it's just a name bound to concrete value, and you can not reassign it (but you can rebound it to another value).First parameter of function
index-filter
is predicate, that means function that returntrue
orfalse
.#{\a}
it's a data structureset
, but it also can be treated like a function. If you pass element as argument to set function it returns this argument (like true) if element exists and nil (like false) otherwise. So you can think about this set predicate as anonymous function written in more understandable way#(contains? #{\a} %)
Autres conseils
pred
is a function - #{\a}
is a set containing the character a. In Clojure, a set is a function which returns true if its argument \a
is contained by it. You could also use #(= % \a)
or (fn [x] (= \a x))
.
As the other answer implies, "no state was created in the making of this example." idx
and elt
function like variables, but are local only to the for
sequence comprehension, so the code is more compact, not stateful, and arguably clearer (once you're used to sequence comprehensions, at least :-) ) -- perhaps the text is not optimally clear on this point.