不更新循环内的向量

时间:2017-02-20 04:37:41

标签: clojure

我正在努力教自己。这只是一个简单的函数,它接受一个值并将每个前面的值相加并返回这些值的总和。

问题是,在loop函数中,numbers未使用conj进行修改,就像我期望的那样 - numbers只保留一个空向量。那是为什么?

(defn sum                        
  [number]                       
  (do (def numbers (vector))     
    (loop [iteration number]     
      (if (> iteration 0)        
        (conj numbers iteration) 
        (recur (dec iteration))))
    (map + numbers)))

2 个答案:

答案 0 :(得分:4)

一些提示(不是答案):

  • 不要使用do
  • 在函数中使用let,而不是def
  • 使用conj之前的返回结果,或者它什么都不做。
  • 将结果传回recur

此外,您的sum函数会忽略其number参数。

我认为您在number(想要添加的内容的数量)和numbers(内容本身)之间感到困惑。记住,

  • 向量(和其他数据结构)知道它们有多长;和
  • 他们经常像以下一样迅速而简洁地处理 序列,使用firstrest代替索引。

您要搜索的代码模式非常常见,以至于它已在名为reduce的标准高阶函数中捕获。你可以得到你想要的效果......

(defn sum [coll] (reduce + coll))

(def sum (partial reduce +))

例如,

(sum (range 10))
;45

有些偏离主题:

如果我是你,而我曾经是,我会浏览网上提供的一些精美的clojure教程,使用REPL手持。您可以开始查看herehere。请享用!

答案 1 :(得分:0)

由于以下三个主要原因,您的功能无效:

  • 你假设conj会更新变量numbers的值(但实际上它会返回绑定到另一个名称的副本)
  • 你使用了loop/recur模式,就像在经典命令式中一样(它的工作方式不同)
  • map
  • 的使用不当

缩略图给出了惯用的答案,但这里正确使用了您的模式:

(defn sum
  [number]
  (loop [iteration number
         numbers []]
    (if (<= iteration 0)
          (reduce + numbers)
          (recur (dec iteration) (conj numbers iteration)))))

循环/重复模式使用recur传递的更新值执行其正文。 重新更新loop后列出的值。这里,虽然迭代严格为正,但执行recur。但是,当迭代次数达到0时,对多次递归的结果执行(reduce + numbers)(实际求和),因此递归结束。