附加到Clojure循环中的数组
我正试图编写一个函数,将0和50之间的所有3和5的倍数相加,但Clojure似乎决心在我告诉它时不将正确的值添加到我的列表中附加到Clojure循环中的数组,clojure,Clojure,我正试图编写一个函数,将0和50之间的所有3和5的倍数相加,但Clojure似乎决心在我告诉它时不将正确的值添加到我的列表中 (conj-toSum计数器)表单应该将当前数字附加到toSum数组,当循环退出时(reduce+toSum)表单应该将数组中的所有内容添加到一起 目前,当调用reduce函数时,toSum总是空的,因为conj函数没有完成它应该做的事情。我一定是在什么地方搞砸了我的逻辑,但我似乎弄不明白 (defn calculate [target] (loop [counter
(conj-toSum计数器)
表单应该将当前数字附加到toSum数组,当循环退出时(reduce+toSum)
表单应该将数组中的所有内容添加到一起
目前,当调用reduce
函数时,toSum
总是空的,因为conj
函数没有完成它应该做的事情。我一定是在什么地方搞砸了我的逻辑,但我似乎弄不明白
(defn calculate [target]
(loop [counter target
toSum []]
(if (= 0 counter)
(reduce + toSum)
(if (or (= 0 (mod counter 3)) (= 0 (mod counter 5)))
(do (conj toSum counter)
(println toSum)
(recur (dec counter) toSum))
(recur (dec counter) toSum)))))
conj
返回一个新集合,它不会改变当前集合。您需要分配新集合并使用该集合重复出现:
(let [nextSum (conj toSum counter)]
(println nextSum)
(recur (dec counter) nextSum))
更实用、更惯用的方法:
(defn multiple-of-3-or-5? [n]
(or (zero? (mod n 3)) (zero? (mod n 5))))
(defn calculate-functional [target]
(->> (range 1 (inc target))
(filter multiple-of-3-or-5?)
(apply +)))
是线程最后一个宏,此宏采用传递的第一个表单(范围表单)并将其作为下一个表单(过滤器表单)中的最后一项插入,而不是采用此新表单并将其作为应用表单中的最后一项插入。因此,该宏在以下情况下转换计算函数
函数:
(apply + (filter is-multiple-3-or-5?
(range 1 (inc target))))
在这种情况下,thread last宏并不是一个巨大的改进,但是当“管道”中有更多步骤时,使用可以明显更容易阅读
(范围1(inc-target))
表单在REPL处创建一个从1开始到目标结束的值:
(range 1 10)
=> (1 2 3 4 5 6 7 8 9)
下一个表达式是(filter multiple-of-3-or-5?
,保留谓词为true的序列元素。最后,(apply+
用于将+
应用于序列的所有元素。您也可以在这里使用(reduce+
,我只是想展示非常有用的应用程序 toSum
不是数组,它是一个PersistentVector
,conj
只适用于不可变类型,它返回对输入的修改,保持原始输入不变(正如@Lee在回答中指出的),上述方法的另一个好处是,您可以轻松地调整解决方案,以接受用于筛选的谓词作为函数的另一个参数,从而使calculate函数成为一个高阶函数,可用于对由不同谓词筛选的范围求和