在Clojure/Script中,contains?
函数可用于检查后续get
是否成功。我相信Clojure版本将在不检索值的情况下进行测试。ClojureScript版本使用get
,会检索该值。
是否有等效的函数可以测试get-in
使用的通过映射的路径是否会成功?在不检索值的情况下进行测试?
例如,这里有一个contains-in?
的天真实现,类似于contains?
的ClojureScript版本,它在进行测试时检索值
(def attrs {:attrs {:volume {:default "loud"}
:bass nil
:treble {:default nil}}})
(defn contains-in? [m ks]
(let [sentinel (js-obj)]
(if (identical? (get-in m ks sentinel) sentinel)
false
true)))
(defn needs-input? [attr-key]
(not (contains-in? attrs [:attrs attr-key :default])))
(println "volume: needs-input?: " (needs-input? :volume))
(println " bass: needs-input?: " (needs-input? :bass))
(println "treble: needs-input?: " (needs-input? :treble))
;=>volume: needs-input?: false
;=> bass: needs-input?: true
;=>treble: needs-input?: false
地图上的任何";属性";不包含默认值的需要用户输入。(nil
是可接受的默认值,但缺少值则不然。(
(defn contains-in? [m ks]
(let [ks (seq ks)]
(or (nil? ks)
(loop [m m, [k & ks] ks]
(and (try
(contains? m k)
(catch IllegalArgumentException _ false))
(or (nil? ks)
(recur (get m k) ks)))))))
BTW,查看clojure.lang.RT
源中的相关函数,我注意到当contains?
和get
的第一个参数是字符串或Java数组时,它们的行为可能有点错误,如下所示:
user=> (contains? "a" :a)
IllegalArgumentException contains? not supported on type: java.lang.String
user=> (contains? "a" 0.5)
true
user=> (get "a" 0.5)
a
user=> (contains? (to-array [0]) :a)
IllegalArgumentException contains? not supported on type: [Ljava.lang.Object;
user=> (contains? (to-array [0]) 0.5)
true
user=> (get (to-array [0]) 0.5)
0
user=> (contains? [0] :a)
false
user=> (contains? [0] 0.5)
false
user=> (get [0] 0.5)
nil