1

I have this:

(defn my-page []
  (layout/render
   "page1.html" ({:articles (map
                             #(update % :field1 (fn [d] (something.... )))
                              (db/get-all-articles))})))
                            ; how can I call map again to process other fields?
                            ; (map for :field2 .... ???? how?)
                            ; (map for :field3 .... ???? how?)     

I want to preprocess other fields also. How can I properly do that? I mean, since I already have the variable :article and function map, how would I do map again for other fields such as :field2 and field3?

2 Answers2

0

Use a threading macro:

(def m {:field1 1
        :field2 2
        :field3 3})

(-> m
  (update :field1 (fn [v1] ...))
  (update :field2 (fn [v2] ...))
  (update :field3 (fn [v3] ...)))

It's equivalent to:

(update
  (update 
    (update m :field1 (fn [v1] ...))
    (fn [v2] ...))
  (fn [v3] ...))

You can enclose such logic in a function and use it to map all the articles.

Piotrek Bzdyl
  • 12,965
  • 1
  • 31
  • 49
  • what's the `m`? is it data that `db/get-all-articles` returns? –  May 31 '16 at 12:28
  • It's an example map object (e.g. with your article data). – Piotrek Bzdyl May 31 '16 at 12:29
  • doesn't it create a new data structure each time? or is it impossible to avoid it in this case? –  May 31 '16 at 15:29
  • Yes, it will create the new map value for each update operation. However, they won't be a full copies as it is a [persistent data structure](http://clojure.org/reference/data_structures#Collections). You might use [`reduce-kv`](http://clojuredocs.org/clojure.core/reduce-kv) as suggested by @leetwinski or use [transients](http://clojure.org/reference/transients) to avoid intermediate results. I would argue that the threading macro is the most readable version and would use it until I discover that this is a performance hot spot and then look for alternative implementations. – Piotrek Bzdyl May 31 '16 at 15:40
0

you could also generalize these updates with reduction:

user> (def items {:field1 1
                  :field2 2
                  :field3 3})
#'user/items
user> (reduce-kv update items {:field1 inc
                               :field2 dec
                               :field3 #(* % 2)})
{:field1 2, :field2 1, :field3 6}
leetwinski
  • 17,408
  • 2
  • 18
  • 42