要测试"get-in"是否成功的函数



在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

最新更新