ClojureScriptの標準にある関数js->clj
はJavaScriptのオブジェクトをClojureScriptのマップに変換したりするものですが、効かないときがあります。
sample.cljs
(ns sample.core
(:require [lt.objs.editor :as editor]
[lt.objs.editor.pool :as pool]))
(def cm (editor/->cm-ed (pool/last-active)))
(def cursor (.getCursor cm))
(js->clj cursor)
上のようにカーソルをjs->clj
で変換しようとしてもうまくいかず
(assoc (js->clj cursor) :a :b)
なんてすると
Error: No protocol method IAssociative.-assoc defined for type object: [object Object]
と怒られます。
この原因は
https://github.com/clojure/clojurescript/blob/master/src/cljs/cljs/core.cljs
のjs->clj
を見るとわかりますがcondの中の
(identical? (type x) js/Object)
の条件が厳しいのが原因です。
代わりに
sample2.cljs
(ns sample.core
(:require [lt.objs.editor :as editor]
[lt.objs.editor.pool :as pool]
[lt.util.cljs :as c]))
(def cm (editor/->cm-ed (pool/last-active)))
(def cursor (.getCursor cm))
(c/js->clj cursor)
のようにlt.util.cljs/js->clj
を使うと変換できたりします。
https://github.com/LightTable/LightTable/blob/master/src/lt/util/cljs.cljs を見ると条件が
(or force-obj
(identical? x (js/Object x))
(identical? (type x) js/Object)
(identical? (type x) js/global.Object))
になっています。
js->clj
のオプションには:keywordize-keys
がありますが、lt.util.cljs
の方には追加で:force-obj
オプションもあります。