Clojure:惯用的召唤方式包含?在一个懒惰的序列

nan*_*sen 10 clojure lazy-sequences

是否有一种惯用的方法来确定LazySeq是否包含元素?从Clojure 1.5开始,调用contains?抛出IllegalArgumentException:

IllegalArgumentException contains? not supported on type: clojure.lang.LazySeq      
clojure.lang.RT.contains (RT.java:724)
Run Code Online (Sandbox Code Playgroud)

在1.5之前,据我所知,它总是返回false.

我知道调用contains?LazySeq可能永远不会返回,因为它可能是无限的.但是如果我知道它不是并且不关心它是否被热切评估呢?

我想出的是:

(defn lazy-contains? [col key]
  (not (empty? (filter #(= key %) col))))
Run Code Online (Sandbox Code Playgroud)

但它感觉不太对劲.有没有更好的办法?

Cho*_*ser 11

首先,懒惰的seqs不能有效地检查会员资格.考虑使用集合而不是懒惰的seq.

如果一套是不切实际的,那么你的解决方案也不错.一些可能的改进:

  1. "不空"有点尴尬.只使用seq就足以获得用户可以在if中使用的nil-or-truthy值.如果你想要true或false,你可以用布尔值包装它.

  2. 由于您只关心第一场比赛,您可以使用一些而不是过滤器和seq.

  3. 编写等式谓词的一种简便方法是使用文字集,如#{key},但如果key为nil,则无论nil是否为n,这将始终返回nil.

一起给你:

(defn lazy-contains? [col key]
  (some #{key} col))
Run Code Online (Sandbox Code Playgroud)


dfr*_*man 5

如果您在示例中使用some而不是,filter一旦找到值,您将立即获得返回,而不是强制评估整个序列。

(defn lazy-contains? [coll key]
  (boolean (some #(= % key) coll)))
Run Code Online (Sandbox Code Playgroud)

编辑:如果您不将结果强制为布尔值,请注意,如果未找到密钥,您将获得nilfalse不是。