是否有一种惯用的方法来确定LazySeq是否包含元素?从Clojure 1.5开始,调用contains?
会抛出IllegalArgumentException:
IllegalArgumentException contains? not supported on type: clojure.lang.LazySeq
clojure.lang.RT.contains (RT.java:724)
在1.5之前,据我所知,它总是返回false。
我知道在LazySeq上调用contains?
可能永远不会返回,因为它可以是无限的。但是如果我知道它不是并且不关心它是否被热切评估呢?
我想出的是:
(defn lazy-contains? [col key]
(not (empty? (filter #(= key %) col))))
但感觉不太对劲。还有更好的方法吗?
答案 0 :(得分:11)
首先,懒惰的seqs无法有效检查会员资格。考虑使用集合而不是惰性seq。
如果一套不切实际,你的解决方案也不错。一些可能的改进:
“非空”有点尴尬。只使用seq就足以获得用户可以在if中使用的nil-or-truthy值。如果你想要true或false,你可以用布尔值包装它。
由于您只关心第一场比赛,您可以使用一些而不是过滤器和seq。
编写等式谓词的一种简便方法是使用文字集,如#{key},但如果key为nil,则无论nil是否为n,都将返回nil。
所有这些一起给你:
(defn lazy-contains? [col key]
(some #{key} col))
答案 1 :(得分:4)
如果您在示例中使用some
而不是filter
,则会在找到值后立即返回,而不是强制评估整个序列。
(defn lazy-contains? [coll key]
(boolean (some #(= % key) coll)))
修改:如果您没有将结果强制转换为布尔值,请注意,如果找不到密钥,您将获得nil
而不是false
。