请解释下面的Clojure代码

Igo*_*pov 6 clojure

我找到了以下代码(在这篇博文中解决了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)))
Run Code Online (Sandbox Code Playgroud)

我发现困难的部分是:(reductions #(rem %1 %2) amount denominations).

正如我发现的那样,简化只是根据某个给定的函数逐步计算得到的集合.示例:(reductions + [1 2 3])给出[1 3 6].

1         ; first  element
1 + 2     ; second element
1 + 2 + 3 ; third  element
Run Code Online (Sandbox Code Playgroud)

计算余数的下一个函数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]
Run Code Online (Sandbox Code Playgroud)

最后一步是删除匿名函数,如本博文中所述.

在这里,事情变得混乱(至少对我来说):rem需要2个参数,我不知道它们在使用数组时的应用方式[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?
Run Code Online (Sandbox Code Playgroud)

有人可以解释一下,这个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
Run Code Online (Sandbox Code Playgroud)

有人可以指向一个网站/书籍/任何解释Clojure技巧的内容,例如"匿名函数的特殊表格"吗?大多数资源只提供最简单的结构(类似于所有其他lisp衍生物的结构),而不涉及Clojure的复杂性.我找到了一个看起来很不错的网站(并且还解释了我上面提到的匿名功能).还有其他此类资源吗?

sou*_*eck 5

这个:

(reductions #(rem %1 %2) amount denominations)
Run Code Online (Sandbox Code Playgroud)

相当于:

(reductions rem amount denominations)
Run Code Online (Sandbox Code Playgroud)

而且你注意到了

(reductions function start collection) 
Run Code Online (Sandbox Code Playgroud)

返回减少collectionwith 的中间结果序列function(start作为第一步减少的第一个参数).function必须采取两个参数.

结果如下:

(reductions function start [1 2 3 4 5]) 
Run Code Online (Sandbox Code Playgroud)

((function start 1) (function (function start 1) 2) ...) 
Run Code Online (Sandbox Code Playgroud)

#(rem %1 %2)语法仅仅是定义匿名函数,它接受两个参数(简写%1%2),要求rem对他们并返回结果.

它相当于:

(fn [a b] (rem a b))
Run Code Online (Sandbox Code Playgroud)