請考慮這段代碼。如何避免兩次調用函數(recur ..)
(loop [k from res '()]
(if (< (count res) n)
(recur (next-num k) (conj res (next-num k)))
(sort res)))
現在,假設函數(next-num k)
執行了一些昂貴的計算。我們負擔不起這兩次。什麼是替代方案?我是Clojure的新手,並不瞭解許多基本功能。但我相信肯定有辦法。
請考慮這段代碼。如何避免兩次調用函數(recur ..)
(loop [k from res '()]
(if (< (count res) n)
(recur (next-num k) (conj res (next-num k)))
(sort res)))
現在,假設函數(next-num k)
執行了一些昂貴的計算。我們負擔不起這兩次。什麼是替代方案?我是Clojure的新手,並不瞭解許多基本功能。但我相信肯定有辦法。
使用let
:
(loop [k from res '()]
(if (< (count res) n)
(let [the-next-num (next-num k)]
(recur the-next-num (conj res the-next-num)))
(sort res)))
像@NathanDavis說,let
允許你命名的中間值:
(loop [k from res '()]
(if (< (count res) n)
(let [next-k (next-num k)]
(recur next-k (conj res next-k)))
(sort res)))
然而,在達到了loop
之前,它的價值看,如果你可以撰寫核心功能達到相同的效果。通常,你可以寫一些不那麼複雜的東西,並揭示重要的細節。
代碼的肉涉及構建next-num
的重複應用程序的序列。幸運的是,這有一個核心功能:iterate
。使用iterate
,我們可以創造價值的無限慵懶的序列:
(iterate next-num from)
; => (from, from', from'', ...)
然而,我們不希望第一這些值。我們能獲得與,以及序列的其餘部分,rest
:
(rest
(iterate next-num from))
; => (from', from'', from''', ...)
在這一點上,我們可以抓住n
值與take
:
(take n
(rest
(iterate next-num from)))
; => (from', from'', from''')
最後,我們可以將這些n
值進行排序:
(sort
(take n
(rest
(iterate next-num from))))
; => (from'', from', from''')
當然,深層嵌套函數調用很快變得尷尬。穿線宏->>
(像它的兄弟->
)是有點語法糖,讓我們重新安排我們的代碼到的東西更好一點:
(->>
(iterate next-num from)
rest
(take n)
sort)
所以,你可以看到序列操作功能強大的庫如何讓我們擺脫低級循環。
真的很棒的解釋。雖然,我已經接受了另一個答案,因爲「let」實際上正是我的問題的答案。但是這種方法絕對和明確地更好。 –
或者,避免循環完全:'( - >> (迭代從明年-NUM) 休息 (取n) 排序)' – Beyamor
@Beyamor:您的建議正在般的魅力。但我不知道爲什麼。你是否願意詳細說明,可能是在你的一個單獨的答案。 –
謝謝,內森。這就是訣竅。 –