使用clojure范围的Lazy-seq生成器

时间:2016-03-06 05:58:01

标签: clojure lazy-loading lazy-evaluation

说我要创建一个从1到m的所有数字的延迟序列,其m的最大公约数等于1

(def m 38941629971148227236N)
(def possible-e
  (lazy-seq (filter #(= 1 (gcd % m)) (range 1 m) ))
  )

然后我可以take

那样的序列
(take 10 possible-e)
=> (1 3 5 7 9 11 13 15 17 19)

但是当我尝试以不同的方式做同样的事情时,事情就不起作用了。我认为它正在计算所有数字,因为它可以永远打印任何东西:

(def possible-e
  (lazy-seq (filter #(= 1 (gcd % m)) (reverse (range 1 m)) ))
  )

为什么它的工作方式不一样?什么是解决方案?

2 个答案:

答案 0 :(得分:2)

问题在于:

(reverse (range 1 m))

在您的代码迁移到filter之前,它必须计算完整的range。您可以使用带有否定步骤的range

(def possible-e
  (lazy-seq (filter #(= 1 (gcd % m)) (range (dec m) 0 -1)))
)

答案 1 :(得分:1)

扩展评论:

  • filter是懒惰的,因此lazy-seq在两种情况下都是多余的。
  • 不要(def m ...)。使possible-e成为带参数m的函数。

所以我们得到

(defn possible-e [m]
  (filter #(= 1 (gcd % m)) (range 1 m)))

(def m 38941629971148227236N)

(defn possible-e [m]
  (filter #(= 1 (gcd % m)) (reverse (range 1 m))))