我使用函数iterate
创建了一个惰性序列。序列不断为每个项目生成新值。然而,在某一点上,所产生的价值并没有意义,并且#34;不再,所以他们没用。这应该是懒惰序列的结束。这是抽象形式的预期行为。
我的方法是让序列产生值。一旦检测到它们不再有用,序列将只发出零值。然后,序列将被包裹起来,以使其有限。
简化为:
(take-while (comp not nil?)
(iterate #(let [v (myfunction1 %)]
(if (mypred? (myfunction2 v)) v nil)) start-value))
这有效,但这里出现两个问题: 用nil作为"塞子"来模拟有限的懒惰序列通常是个好主意,还是有更好的方法?
第二个问题与我实现上述机制的方式有关,特别是在迭代内部。 问题是:我需要一个函数来获取一个值,然后一个谓词来测试它是否有效,如果是:需要传递第二个函数,否则:返回nil。 我正在寻找一种不那么迫切的方式来实现这一点,更具体地省略了let语句。相反,像这样:
(defn pass-if-true [pred v f]
(when (pred? v) (f v)))
#(pass-if-true mypred? (myfunction1 %) myfunction2)
现在,我将继续这样做:
(comp #(when (mypred? %) (myfunction2 %)) myfunction1)
答案 0 :(得分:3)
用nil作为“塞子”对有限懒惰序列进行建模通常是个好主意,还是有更好的方法?
nil
是结束有限懒惰序列的惯用方法。
关于第二个问题,请尝试这样写:
(def predicate (partial > 10))
(take-while predicate (iterate inc 0))
;; => (0 1 2 3 4 5 6 7 8 9)
此处inc
采用先前的值并生成下一个值,predicate
测试值是否良好。第一次predicate
返回false
时,序列终止。
答案 1 :(得分:0)
使用nil的返回值可以使惰性序列终止。
例如,此代码计算两个整数的最大公约数:
(defn remainder-sequence [n d]
(let [[q r] ((juxt quot rem) n d)]
(if (= r 0) nil
(lazy-seq (cons r (remainder-sequence d r))))))
(defn gcd [n d]
(cond (< (Math/abs n) (Math/abs d)) (gcd d n)
(= 0 (rem n d)) d
:default (last (remainder-sequence n d))))
(gcd 100 32) ; returns 4