测试“进入”是不是成功的函数
Posted
技术标签:
【中文标题】测试“进入”是不是成功的函数【英文标题】:A Function to Test if `get-in` will Succeed测试“进入”是否成功的函数 【发布时间】:2020-12-25 06:46:25 【问题描述】:在 Clojure/Script 中,contains?
函数可用于检查后续 get
是否会成功。我相信 Clojure 版本会在不检索值的情况下进行测试。 ClojureScript 版本使用get
并且确实检索该值。
是否有一个等效的函数可以测试get-in
使用的通过地图的路径是否会成功?那是在不检索值的情况下进行测试吗?
例如,这里有一个简单的 contains-in?
实现,类似于在进行测试时检索值的 ClojureScript 版本的 contains?
。:
(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
是可接受的默认值,但缺失值不是。)
【问题讨论】:
你为什么要求“在没有检索值的情况下进行测试”?昂贵的部分是进行密钥查找;一旦你这样做了,就可以免费获得价值。 @amalloy:好奇。 Clojures 的实现似乎很麻烦,我只是想知道为什么。 用例是什么?如果只是为了防止丢失数据或键入错误的密钥,请在此处查看grab
、fetch
和 fetch-in
函数:cljdoc.org/d/tupelo/tupelo/20.08.27b/api/tupelo.core#fetch-in
@Alan:用例与示例非常相似,但映射更深。一个人定义了一种文档类型,包括它必须具有、应该具有、不应该具有的特征等。其他人的任务是编写这些类型的文档。此处说明的步骤是创建一组可应用于第二组编写的文档的规则。除了验证之外,它还应该提供有用的错误消息和指导。
在这一点上感觉就像你正在重新发明 clojure.spec ......?
【参考方案1】:
(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)))))))
顺便说一句,查看the source of 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
【讨论】:
以上是关于测试“进入”是不是成功的函数的主要内容,如果未能解决你的问题,请参考以下文章