2016-05-14 15 views
4

這是計算素數值的書Programming Clojure (2nd edition)中的示例代碼。使用Clojure中的let/fn匹配參數

(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]]

對此代碼的任何解釋?

回答

4

letprimes-from定義爲指用fn定義的函數。

當首次調用primes-from時,11個匹配項nwheel匹配[f & r]wheel指的是一個序列,並且[f & r]需要一個序列 - 這就是括號的含義。 f(「第一個」)將匹配序列中的第一個元素,這將在第一次通過時爲2。 &意味着它後面的參數r(「休息」)旨在匹配序列的全部剩餘部分(以第一次通過時開始於4)。

cycle定義了一個懶序列,那麼什麼匹配r沒有完全展開。)

兩個「素數 - 從」中(let [primes-from ...和 在(fn primes-from ...「素數 - 從」是必要的。第一種情況是允許在primes定義的最後一行中初始調用函數。第二種情況是在fn定義的中間允許按名稱遞歸調用函數。 「primes-from」的最後一個實例還爲該函數提供了一個內部名稱屬性,該屬性在調試過程中可能會有所幫助。

(請注意,是fn定義範圍內的兩個遞歸調用。第一種使用recur,第二個使用primes-from,兩者可以使用primes-from,但它通常最好使用recur,可能的情況下,因爲它不使用該堆棧因此效率更高並且避免了內存不足recur只能用於尾部位置,即當函數中不需要對返回值進行進一步處理時,在第二種情況下不可能使用recur ,因爲返回值將輸入到conslazy-seq。)