我希望有一个函数/宏来检查列表最终具有真值,我希望评估是懒惰的。这是我没有懒惰评估的说明性实现:
(defn eventual [cols]
(or (first cols) (if-let [rs (rest cols)]
(eventual rs))
false))
这是一个简单的例子来说明:
(if (eventual [false (+ 1 2) (* 10000 10000)])
true
false)
我觉得懒惰的评价必然会有一个含义。也许我现在只是蒙蔽双眼。请帮忙。感谢
答案 0 :(得分:2)
您可以检查序列是否包含至少一个带有some
函数的真实元素:
(some identity col)
如果你将一个懒惰的序列传递给col
,它会将其内容评估为第一个真实元素,并且不会实现其余部分:
(let [col (take
10
(iterate
#(do (println "Generating new value from " %) (inc %))
0))]
(some #(> % 5) col))
产生
Generating new value from 0
Generating new value from 1
Generating new value from 2
Generating new value from 3
Generating new value from 4
Generating new value from 5
true
如您所见,值6..9根本不会产生。
您还应该仔细检查传递给col
的{{1}}是否真的很懒,而且还没有实现,因为它可能会让您感到困惑。
答案 1 :(得分:2)
您的eventual
功能尽可能地懒惰。它急切地搜索第一个真实项目然后停止。但它有问题:
(rest ())
是()
,
这是真的。使用next
代替rest
。 (next ())
是nil
,
这是假的。(eventual (repeat false))
。因为递归是
尾递归,您可以在其位置使用recur
来解决此问题。nil
而非false
是不恰当的,
一个集合用完了。所以放弃最后的false
。我们最终
(defn eventual [cols]
(or (first cols) (if-let [rs (next cols)]
(recur rs))))
如果cols
为空,我会感到有些不安。基于the source for some
的代码更清晰:
(defn eventual [coll]
(when (seq coll)
(or (first coll) (recur next coll))))
但使用(some identity col)
,Piotrek建议,可能是最好的。