'jQuery' type function for manipulating clojure maps

clojure, clojurescript, noir

Solution

First of all, you should check out Enlive.

Otherwise: if you want to do what jQuery does (of course very simplified) - as opposed to just calling update-in:

Select:

(defn clj-query-select [obj path]
  (if (empty? path)
    (list obj)
    (when (map? obj)
      (apply concat
        (remove nil? 
          (for [[key value] obj]
            (clj-query-select
              value 
              (if (= key (first path)) (rest path) path))))))))

For call:

(clj-query-select {:a {:b 1} :b 2} [:b])

it should yield:

(1 2)

Update/replace:

(defn clj-query-update [obj path fn]
  (if (empty? path)
    (fn obj)
    (if (map? obj)
      (into obj
        (remove nil?
          (for [[key value] obj]
            (let [res (clj-query-update 
                        value 
                        (if (= key (first path)) (rest path) path)
                        fn)]
          (when (not= res value) [key res])))))
      obj)))

For call:

(clj-query-update {:c {:a {:b 1} :b 2}} [:c :b] #(* % 2))

it should yield:

{:c {:a {:b 2} :b 4}}

I didn't test it thoroughly though.

Problem

Is there a jQuery type function to solve the problem of walking through nested maps? for example, if i have a configuration that looks like this: ``` (def fig {:config {:example {:a "a" :b "b" :c "c"} :more {:a "a" :b "b" :c "c"}}}) ``` I still haven't figured out a great way to manipulate nested persistent data structures with assoc and dissoc. However, if there was a `jquery` style way to manipulate maps, then I can write code like this: ``` (-> fig ($ [:config :example :a] #(str % "a")) ($ [:config :b] #(str % "b"))) Giving this output: {:config {:example {:a "aa" :b "bb" :c "c"} :more {:a "a" :b "bb" :c "c"}}} ``` And something like this for selectors: ``` ($ fig [:config :example :a]) ;=> "a" ($ fig [:config :b]) ;=> {[:config :example :b] "b", ; [:config :more :b] "b"} ``` So in essence, I'm looking for an implementation of `jayq` for manipulation of clojure objects instead of html doms. Thanks in advance!

Original source