在Clojure中使用let / fn匹配参数

时间:2016-05-14 01:08:35

标签: clojure let

这是计算素数值的书Programming Clojure (2nd edition)中的示例代码。

(def primes
  (concat
   [2 3 5 7]
   (lazy-seq
    (let [primes-from
          (fn primes-from [n [f & r]]
            (if (some #(zero? (rem n %))
                      (take-while #(<= (* % %) n) primes))
              (recur (+ n f) r)
              (lazy-seq (cons n (primes-from (+ n f) r)))))
          wheel (cycle [2 4 2 4 6 2 6 4 2 4 6 6 2 6  4  2
                        6 4 6 8 4 2 4 2 4 8 6 4 6 2  4  6
                        2 6 6 4 2 4 6 2 6 4 2 4 2 10 2 10])]
      (primes-from 11 wheel)))))

代码具有定义本地函数primes-from的结构,以便在let表单中使用它。

(def primes
  (concat
   [2 3 5 7]
   (lazy-seq
    (let [primes-from (fn primes-from [n [f & r]] ... ]
      (primes-from 11 wheel)))))

但是,我不确定第一个参数11和第二个参数wheel如何与[primes-from (fn primes-from [n [f & r]] ... ]结构匹配。

另外,我无法看到primes-from参数在定义匿名函数(fn primes-from [n [f & r]]时的作用。

有关此代码的任何解释?

1 个答案:

答案 0 :(得分:4)

let定义primes-from以引用使用fn定义的函数。

首次调用primes-from时,11个匹配nwheel匹配[f & r]wheel指的是序列,而[f & r]指的是序列 - 这就是括号的含义。 f(“first”)将匹配序列中的第一个元素,第一次通过时将是2。 &表示后面的参数r(“rest”)旨在匹配序列的其余部分(第一次从4开始)。

cycle定义了一个惰性序列,因此匹配r的内容未完全展开。)

(let [primes-from ...(fn primes-from ...中的“primes-from” 需要primes中的“primes-from”。第一个实例允许在fn定义的最后一行中对函数进行初始调用。第二个实例允许在fn定义的中间通过名称递归调用函数。最后一个“primes-from”实例也为函数提供了一个内部名称属性,在调试过程中可能会有所帮助。

(请注意,recur定义中有两个递归调用。第一个使用primes-from,第二个使用primes-from。两者都可以使用recur,但它是通常最好在可能的情况下使用recur,因为它不使用堆栈因此更有效并且避免内存不足。recur只能用于尾部位置,即不再使用时处理必须使用函数中返回的值来完成。在第二种情况下不能使用cons,因为返回值将被馈送到lazy-seqNSMutableData。)< / p>