How do I perform a function with side-effects over a vector?
-
02-01-2020 - |
Question
The say-hello-to-first-person works fine, why doesn't say-hello-to-everyone?
(defpartial greeting [name] [:p.alert "Hello " name ", how are you?"]) (defn say-hello [name] (append $content (greeting name))) (defn say-hello-to-first-person [names] (say-hello (first names))) (defn say-hello-to-everyone [names] (map say-hello names)) (say-hello-to-first-person ["Chris" "Tom" "Jim" "Rocky"]) (say-hello-to-everyone ["Chris" "Tom" "Jim" "Rocky"])
Solution
You want doseq
, Clojure's "foreach":
(doseq [name names]
(say-hello name))
map
doesn't work because it produces a lazy sequence: Until you actually access the items in the sequence (which you don't here), none of them will be evaluated, and side effects won't occur.
Another option is to force evaluation by wrapping dorun
around the map
. Thinking about why this works may help your understanding (although doseq
is the idiomatic approach here).
OTHER TIPS
As @edbond says in his comment, map fn don't evaluate until necessary moment because map fn returns a lazy seq.
This is the doc of map fn Returns a lazy sequence consisting of the result of applying f to the set of first items of each coll, followed by applying f to the set of second items in each coll, until any one of the colls is exhausted. Any remaining items in other colls are ignored. Function f should accept number-of-colls arguments.
If you need to be sure that the values are evaluate in one specific part of your code you can use doall or dorun