The*_*tan 2 for-loop list-comprehension clojure
我目前正在学习 Clojure,并且一直坚持列表理解。
\n;; /sf/answers/533764521/\n(defn gen-primes "Generates an infinite, lazy sequence of prime numbers"\n []\n (letfn [(reinsert [table x prime]\n (update-in table [(+ prime x)] conj prime))\n (primes-step [table d]\n (if-let [factors (get table d)]\n (recur (reduce #(reinsert %1 d %2) (dissoc table d) factors)\n (inc d))\n (lazy-seq (cons d (primes-step (assoc table (* d d) (list d))\n (inc d))))))]\n (primes-step {} 2)))\n\n(defn prime-factors-not-working [x]\n (for [y (gen-primes) \n :when (= (mod x y) 0) \n :while (< y (Math/sqrt x))] \n y))\n\n(defn prime-factors-working [x]\n (for [y (gen-primes) \n :while (< y (Math/sqrt x))\n :when (= (mod x y) 0)]\n y))\n\n(prime-factors-working 100)\n;; \xe2\x86\xaa (2 5)\n\n(prime-factors-not-working 100)\n;; Goes into infinite loop\n
Run Code Online (Sandbox Code Playgroud)\n(gen-primes)
是素数的惰性序列。while
工作序列和非工作序列之间的唯一区别是修饰符和的顺序when
。为什么not-working
执行会陷入无限循环?
不起作用的变体在概念上(但实际上不是)扩展为:
(loop [ys (gen-primes)
result []]
(if (seq ys)
(let [y (first ys)]
(if (= (mod x (first ys)) 0) ;; Can be replaced with `(zero? (mod x y))` BTW.
(if (< y (Math/sqrt x))
(recur (next ys) (conj result y))
result)
(recur (next ys) result)))
result))
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,如果(mod x (first ys))
不是 0,它将转到下一个数字 - 不检查它<
,永远如此。
当您交换:when
和时:while
,上面的伪展开中的检查也会交换 - 一旦y
达到 的平方根,就停止迭代x
。