Clojure 创建有限延迟序列

Clojure 创建有限延迟序列,clojure,functional-programming,clojurescript,Clojure,Functional Programming,Clojurescript,我正在使用函数iterate创建一个惰性序列。序列不断在每个项目上生成新值。然而,在某一点上,生成的值“不再有意义”,因此它们是无用的。这应该是延迟序列的结束。这是抽象形式的预期行为 我的方法是让序列产生值。一旦检测到它们不再有用,序列将只发出nil值。然后,序列将被包装一段时间,使其有限 简化: 这是可行的,但这里出现了两个问题: 用nil作为“塞子”对有限的惰性序列建模通常是一个好主意,还是有更好的方法 第二个问题与我实现上述机制的方式有关,特别是在迭代中。 问题是:我需要一个函数来获取一个

我正在使用函数
iterate
创建一个惰性序列。序列不断在每个项目上生成新值。然而,在某一点上,生成的值“不再有意义”,因此它们是无用的。这应该是延迟序列的结束。这是抽象形式的预期行为

我的方法是让序列产生值。一旦检测到它们不再有用,序列将只发出nil值。然后,序列将被包装一段时间,使其有限

简化:

这是可行的,但这里出现了两个问题: 用nil作为“塞子”对有限的惰性序列建模通常是一个好主意,还是有更好的方法

第二个问题与我实现上述机制的方式有关,特别是在迭代中。 问题是:我需要一个函数来获取一个值,然后一个谓词来测试它是否有效,如果是:in需要传递第二个函数,否则:返回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) 
用nil作为“塞子”对有限的惰性序列建模通常是一个好主意,还是有更好的方法

nil
是结束有限延迟序列的惯用方法

关于第二个问题,试着这样写:

(def predicate (partial > 10))
(take-while predicate (iterate inc 0))
;; => (0 1 2 3 4 5 6 7 8 9)

在这里,
inc
获取上一个值并生成下一个值,
谓词
测试值是否正确。第一次
谓词
返回
false
,序列终止。

使用返回值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
(定义余数序列[nd]
(让[[q r]((juxt quot rem)n d)]
(如果(=r 0)无
(惰性序列(consr(余数序列dr‘‘‘‘‘)’))
(一般分类数字[一般分类数字]
(第二部分(<(数学/abs n)(数学/abs d))(gcd n)
(=0(rem n d))d
:默认值(最后一个(余数序列n d)))
(gcd 100 32);返回4

顺便说一句:
(comp不是nil?
(compute nil?
一样好。另外
(if(mypred?(myfunction2 v))v nil)
可以替换为
(when(mypred?(myfunction2 v))v)
谢谢您的回答!我的问题是,转移到你的例子中,inc必须用另一个f包装,比如说str。但我已经知道,在转换为字符串之前,数字不能通过真值测试。嗯,也许我有点忘记了这些seq是懒惰的,所以我可以用一个(map str…)来包装你的整个例子。。。对..?没错。或者用
(comp str inc)
代替
inc
。如果在检查之前需要转换为字符串,但不希望结果中包含字符串<代码>(复合谓词str)
(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