在 clojure 中使用范围的惰性序列生成器

Lazy-seq generator using range in clojure

说我想创建一个从 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)) ))
  )

为什么它的工作方式不同?有什么解决办法?

问题出在这里:

(reverse (range 1 m))

在您的代码可以移动到 filter 之前,它必须计算完整 range。您可以将 range 与负步一起使用:

(def possible-e
  (lazy-seq (filter #(= 1 (gcd % m)) (range (dec m) 0 -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))))