DAY 10
0
Software Development

## 遞迴

### 一般遞迴

``````(defn factorial [n]
(if (= n 1)
1
(*' n (factorial (- n 1)))))
(factorial 10)
;; => 3628800
``````

``````(factorial 10000)
;; => StackOverflowError
``````

### 尾遞迴

``````(defn tail-factorial
([n]
(tail-factorial 1 1 n))
([product counter max-count]
(if (> counter max-count)
product
(tail-factorial (*' counter product)
(+ counter 1)
max-count))))
(tail-factorial 10000)
;; => StackOverflowError
``````

``````(defn recur-factorial [n]
(loop [product 1
counter 1
max-count n]
(if (> counter max-count)
product
(recur (*' counter product)
(+ counter 1)
max-count))))
(recur-factorial 10000)
;; => 28462596809170545189….0000N
``````

## 惰性序列

``````(class (take 10 (range)))
;; => clojure.lang.LazySeq
``````

``````(range 10)
;; => (0 1 2 3 4 5 6 7 8 9)
(range 1 11)
;; => (1 2 3 4 5 6 7 8 9 10)
(range 1 11 2)
;; => (1 3 5 7 9)
(take 5 (range))
;; => (0 1 2 3 4)
``````

``````;; 危險！不要這樣做！！
(range)
``````

`repeat` 創建惰性序列，內容為不斷重複的參數：

``````(take 3 (repeat "Hello"))
;; => ("Hello" "Hello" "Hello")
``````

`iterate` 函式接受兩個參數，第一個參數爲一個函式，這個函式將會不斷地被運算，求值後的結果成爲惰性序列的內容；第二個參數則爲初始值：

``````(take 5 (iterate #(+ % 0.5) 1))
;; => (1 1.5 2.0 2.5 3.0)
``````

`cycle` 函式接受一個群集，群集的內容將會交錯反覆地作爲惰性序列的元素：

``````(take 3 (cycle ["ping" "pong"]))
;; => ("ping" "pong" "ping")
(take 5 (cycle ["ping" "pong"]))
;; => ("ping" "pong" "ping" "pong" "ping")
``````

`map``filter` 函式可以應用在惰性序列上，產生的結果也是惰性序列。以下範例示範了利用 `filter``take` 取得 0 到 100 中頭十個偶數：

``````(take 10 (filter even? (range 0 100)))
;; => (0 2 4 6 8 10 12 14 16 18)
``````

``````(defn fib-seq
"Returns a lazy sequence of Fibonacci numbers"
([]
(fib-seq 0 1))
([a b]
(lazy-seq
(cons b (fib-seq b (+ a b))))))
(take 10 (fib-seq))
;; => (1 1 2 3 5 8 13 21 34 55)
``````

## 回顧

（本篇文章同步刊登於 GitHub，歡迎在文章下方留言或發送 PR 給予建議與指教）