Както каза @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)
И така, можете да видите как една мощна библиотека от функции за манипулиране на последователност ни позволява да се отдалечим от зациклянето на ниско ниво.
person
Beyamor
schedule
18.12.2013