我找到了以下代码(在解决Coin Changer Kata的这篇博文中):
(defn change-for [amount]
(let [denominations [25 10 5 1]
amounts (reductions #(rem %1 %2) amount denominations)
coins (map #(int (/ %1 %2)) amounts denominations)]
(mapcat #(take %1 (repeat %2)) coins denominations)))
我觉得困难的部分是:(reductions #(rem %1 %2) amount denominations)
。
正如我发现的那样,reductions只是根据给定的函数增量地计算结果集合。示例:(reductions + [1 2 3])
给出[1 3 6]
.
1 ; first element
1 + 2 ; second element
1 + 2 + 3 ; third element
下一个计算余数的函数rem仍然非常容易理解。
为了理解其余的代码,我尝试了以下方法:
; first try, to see if this call works
; outside the original code (the change-for function)
(reductions #(rem %1 %2) 17 [10 5 1]) ; --> [17 7 2 0]
; tried to use the reductions which takes only one argument
; notice that 17 is now inside the array
(reductions #(rem %1 %2) [17 10 5 1]) ; --> [17 7 2 0]
; further simplified the expression
(reductions rem [17 10 5 1]) ; --> [17 7 2 0]
最后一步是删除此博客文章中描述的匿名函数。
在这里,事情变得令人困惑(至少对我而言):rem
需要 2 个参数,但我不明白它们在使用 array 时是如何应用的[17 10 5 1]
。我尝试了以下调用:
(rem [17 10 5 1]) ; --> gives error
(rem [17 10 5 1] [17 10 5 1]) ; --> also gives error
(rem 17 10) ; --> works, but how do you use it with collections?
有人可以解释一下,这个rem
函数是如何与函数一起工作的reductions
吗?
我不太明白的另一件事是:这些百分比参数是如何应用的(in #(rem %1 %2)
)?我的意思是他们来自哪里?我尝试通过以下方式调用rem
,但出现错误:(#(rem %1 %2) 17 [10 5 1])
. 该reductions
功能必须在幕后进行某些操作才能使这项工作正常进行,对吗?
一开始我以为那#(rem %1 %2)
是一套。它们以与集合类似的方式声明,并且很容易被滥用(被刚开始使用 Clojure 的人):
(type #{1 2 3}) ; --> clojure.lang.PersistentHashSet
(type #(1 2 3)) ; --> user$eval12687$fn__12688
有人可以将我指向一个站点/书籍/任何解释 Clojure 技巧的东西,例如“匿名函数的特殊形式”吗?大多数资源只给出了最简单的结构(类似于所有其他 lisp 衍生产品的结构),而没有涉及 Clojure 的复杂性。我找到了一个看起来不错的网站(并且还解释了我上面提到的匿名函数)。还有其他这样的资源吗?