通过将前一项乘以常数来构建惰性序列

Ale*_*lva 1 recursion clojure

我从 Clojure 开始,尽管了解递归,但我很难想到为以下函数构建惰性序列的“正确”方法:

我想建立一个从中 C 开始的所有频率的列表。我的第一个元素是 120(中 C 的频率)。为了获得第二个元素,我将第一个元素 120 乘以 1.059463,得到 127.13556。为了得到第三个元素,我将第二个元素 127.13556 乘以 1.059463,等等......

在 Clojure 中执行此操作的最佳方法是什么?

Jar*_*314 5

您可以使用该iterate功能来实现此目的。

(iterate #(* % 1.059463) 120)
Run Code Online (Sandbox Code Playgroud)


如果您计划将其扩展为更复杂的东西,那么您将创建一个在对 的调用中递归调用自身的函数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
Run Code Online (Sandbox Code Playgroud)


如果您开始在紧密循环中使用它,您可能还想生成分块惰性序列。这将预先计算接下来的几个元素,而不是一一计算。

(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))))))))
Run Code Online (Sandbox Code Playgroud)

注意:我建议不要这样做,直到您测量了与计算单个元素相关的性能问题。