clojureでmapを扱う基本的な関数
clojureを何も知らないままとりあえず1つプログラム書いてみて、色々知らないまま書いていたのでとても苦労しました
便利な関数がいっぱいあったのでメモ。
ネストしたmapの操作
jsonを扱っていると時にネストの深いhash-mapをいじらないといけない時がありますね
get-in
こんなxがあったとき、おどろくべきことに一々(:key1 (:key2 ...と書いていました。恐ろしい
user=> (def x {:foo {:bar {:baz 1} :hoge 2}}) #'user/x user=> (:baz (:bar (:foo x))) 1
get-in
という関数がちゃんと用意されていました。
user=> (get-in x [:foo :bar :baz]) 1
assoc-in
key valueを追加したい、もしくは単に値を変えたい場合はassoc-in
assoc-in
を知るまではこんなふうに書いていましたが、
user=> (assoc x :foo (assoc (:foo x) :hoge 10)) {:foo {:hoge 10, :bar {:baz 1}}}
これで十分です。
user=> (assoc-in x [:foo :bar :piyo] 10) {:foo {:hoge 2, :bar {:piyo 10, :baz 1}}}
update-in
関数を適用して更新したいときはupdate-in
user=> (defn f [x] (+ x 10)) #'user/f user=> (update-in x [:foo :hoge] f) {:foo {:hoge 12, :bar {:baz 1}}}
ちょっと違うかもだけどけど->
第1引数(?)にその後に続く関数(?)を適用していける感じのマクロ。 これを使えばこんな風になります
user=> (-> x :foo :bar :baz) 1
jsonを使うときのメモ
clojureでjsonといえば、https://github.com/clojure/data.jsonを使いますよね(多分)
これ、普通に使うと文字列からjsonにデコードする時にキーがstringになってしまうんですね。
これは不便。
(get (get (get x "foo") "bar") "baz")
みたいになってしまう。(はず)
しかし、githubのREADMEの例にも書いてあるように、
(json/read-str "{\"a\":1,\"b\":2}" :key-fn keyword)
このように:key-fn keyword
を指定すればキーがKeywordになってくれます!
便利