Below is my attempt to iterate a sequence of maps; the code fails due to the casting error: Exception in thread "main" java.lang.RuntimeException: java.lang.ClassCastException: clojure.lang.Cons cannot be cast to java.util.Map$Entry.
Can anyone explain/demonstrate how I should iterate the result-set? Thanks.
(with-connection db
(with-query-results rs ["select category from users group by category"]
(doall
(for [s [rs]]
(do (println (val s)))))))
You wrapped the
rsinto a vector. Soswill be bound to the whole sequence, not the individual map entries. So when you callvalit doesn’t know what to do with a sequence. Hence the exception. This should work:However the ugly
doallanddoaround theforshould ring a bell, that something could be improved. And indeedforis used to construct another lazy sequence. This does not work well with side-effects as you intend in your example. You should usedoseqin this case.The interface for the bindings of
doseqis identical to that offor. However it executes things immediatelly, and thusly realises any side-effects immediatelly. If you put multiple expressions in the body of a for, you have to wrap it into ado. This is a reminder that the body should produce a value. Multiple expressions however indicate side-effects.doseqtherefore wraps the body into adofor you. So you can easily have multiple expressions. For illustration:As a rule of thumb: you need side-effects? Look for things starting in
do!As a rule of thumb 2: if something looks ugly (see above comparison), this should ring a bell.