我从 Clojure 开始,尽管了解递归,但在思考为以下函数构建惰性序列的“正确”方法时遇到了麻烦:
我想建立一个从中间 C 开始的所有频率的列表。我的第一个元素是 120(中间 C 的频率)。为了得到第二个元素,我将第一个元素 120 乘以 1.059463 得到 127.13556。为了获得第三个,我将第二个元素 127.13556 乘以 1.059463 等等……
在 Clojure 中执行此操作的最佳方法是什么?
您可以使用该iterate
功能。
(iterate #(* % 1.059463) 120)
如果您打算将其扩展为更复杂的东西,那么您将创建一个函数,该函数在对lazy-seq
. (这就是iterate
内部所做的。)
(defn increasing-frequencies
([] (increasing-frequencies 120))
([freq]
(cons freq (lazy-seq (increasing-frequencies (* freq 1.059463))))))
(nth (increasing-frequencies) 2) ;; => 134.69542180428002
如果你开始在一个紧密的循环中使用它,你可能还想生成一个分块的惰性序列。这将预先计算接下来的几个元素,而不是一一计算。
(defn chunked-increasing-frequencies
([] (chunked-increasing-frequencies 120))
([freq]
(lazy-seq
(let [b (chunk-buffer 32)]
(loop [i freq c 0]
(if (< c 32)
(do
(chunk-append b i)
(recur (* i 1.059463) (inc c)))
(chunk-cons (chunk b) (chunked-increasing-frequencies i))))))))
注意:在您测量与计算单个元素相关的性能问题之前,我建议您不要这样做。