【问题标题】:Please explain me the following Clojure code请向我解释以下 Clojure 代码
【发布时间】:2012-12-09 00:54:59
【问题描述】:

我找到了以下代码(在this blog post 中解决了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]

最后一步是删除this blog post 中描述的匿名函数。

在这里,事情变得令人困惑(至少对我来说):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?

谁能解释一下,rem 函数如何与 reductions 函数一起工作?

我不太明白的另一件事是:这些百分比参数是如何应用的(在#(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 的复杂性。我发现a site 看起来不错(并且还解释了我上面提到的匿名函数)。 还有其他此类资源吗?

【问题讨论】:

    标签: clojure


    【解决方案1】:

    这个:

    (reductions #(rem %1 %2) amount denominations)
    

    等价于:

    (reductions rem amount denominations)
    

    正如你所注意到的

    (reductions function start collection) 
    

    返回用function 减少collection 的中间结果序列(以start 作为减少第一步的第一个参数)。 function 必须带两个参数。

    所以结果:

    (reductions function start [1 2 3 4 5]) 
    

    ((function start 1) (function (function start 1) 2) ...) 
    

    #(rem %1 %2) 语法只是定义匿名函数的简写,它接受两个参数(%1%2),对它们调用 rem 并返回结果。

    相当于:

    (fn [a b] (rem a b))
    

    【讨论】:

      猜你喜欢
      • 2012-04-09
      • 2023-02-08
      • 1970-01-01
      • 1970-01-01
      • 2011-09-06
      • 2015-08-28
      • 2016-01-02
      • 1970-01-01
      • 2018-11-30
      相关资源
      最近更新 更多