Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mapping over a vector performing side-effects

Tags:

clojure

I am attempting to iterate over a vector of "lines" in Clojure. Essentially, it looks like:

[{:start {:x 1 :y 3 :z 4}, :end {:x 3 :y 7 :z 0}}, ...]

I would like to apply a function that prints each of these "lines" onto a new line, ala:

(map #(println %) vector-of-lines)

but that doesn't appear to call the function. Should I not be using the "map" function in this instance?

like image 757
sdasdadas Avatar asked Jun 01 '12 21:06

sdasdadas


4 Answers

(dorun (map println vector-of-lines))

dorun forces the evaluation of the lazy sequence, but also discards the individual results of each of item in the sequence. This is perfect for sequences that are purely for side-effects which is exactly what you want here.

like image 112
Julien Chastang Avatar answered Nov 16 '22 04:11

Julien Chastang


map is lazy and won't realize results unless you ask for them. If you want to perform a side effect for each element in a sequence, and don't care about the return value, use doseq:

;; returns nil, prints each line
(doseq [line vector-of-lines]
  (println line))

If you do care about the return value, use (doall):

;; returns a sequence of nils, prints each line
(doall (map println vector-of-lines))
like image 27
Justin Kramer Avatar answered Nov 16 '22 03:11

Justin Kramer


To add to Justin's answer, doseq is a macro, and thus carries with it all the limitations of macros.

I would write a foreach function that internally uses doseq.

user=> (defn foreach [f xs] (doseq [x xs] (f x)))
#'user/foreach

user=> (foreach println [11 690 3 45])
11
690
3
45
nil
like image 4
missingfaktor Avatar answered Nov 16 '22 04:11

missingfaktor


Since Clojure 1.7 there is run! which does what you want. The naming of this method may be related to the workaround with dorun and map. Be careful with using map for such occasions. Suppose that you make another call to map inside your function that you passed in. That will require walking the sequence as well. Thus, you will need to use dorun twice.

like image 1
m33lky Avatar answered Nov 16 '22 02:11

m33lky