问题描述
是否有一种惯用的方法来确定 LazySeq 是否包含一个元素?从 Clojure 1.5 开始,调用 contains?
会抛出 IllegalArgumentException:
Is there an idiomatic way of determining if a LazySeq contains an element? As of Clojure 1.5 calling contains?
throws an IllegalArgumentException:
IllegalArgumentException contains? not supported on type: clojure.lang.LazySeq
clojure.lang.RT.contains (RT.java:724)
在 1.5 之前,据我所知,它总是返回 false.
Before 1.5, as far as I know, it always returned false.
我知道在 LazySeq 上调用 contains?
可能永远不会返回,因为它可以是无限的.但是如果我知道它不是并且不在乎它是否被急切地评估怎么办?
I know that calling contains?
on a LazySeq may never return as it can be infinite. But what if I know it isn't and don't care if it is evaluated eagerly?
我想到的是:
(defn lazy-contains? [col key]
(not (empty? (filter #(= key %) col))))
但是感觉不太对.有没有更好的办法?
But it doesn't feel quite right. Is there a better way?
推荐答案
首先,lazy seqs 在检查成员资格方面效率不高.考虑使用集合而不是惰性序列.
First, lazy seqs are not efficient for checking membership. Consider using a set instead of a lazy seq.
如果一套不切实际,你的解决方案还不错.一些可能的改进:
If a set is impractical, your solution isn't bad. A couple of possible improvements:
非空"有点别扭.仅使用 seq 就足以获得您的用户可以在 if 中使用的 nil-or-truthy 值.如果您想要 true 或 false,您可以将其包装在布尔值中.
"Not empty" is a bit awkward. Just using seq is enough to get a nil-or-truthy value that your users can use in an if.You can wrap that in boolean if you want true or false.
因为你只关心第一个匹配,所以你可以用 some 代替 filter 和 seq.
Since you only care about the first match, you can use some instead of filter and seq.
写等式谓词的一种方便的方法是使用文字集,如#{key},但如果 key 为 nil,则无论是否找到 nil,都将始终返回 nil.
A convenient way to write an equality predicate is with a literal set, like #{key}, though if key is nil this will always return nil whether nil is found our not.
共同为您提供:
(defn lazy-contains? [col key]
(some #{key} col))
这篇关于Clojure:调用包含的惯用方式?在惰性序列上的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!