了解复发

Understanding recur

正在尝试这段代码,但似乎不太正常..

(defn- multiple_of?
  [div num]
  (= (mod num div) 0))

(defn sum_of_multiples_from 
  ([start] (sum_of_multiples_from start 0))
  ([start total]
   (if (<= start 0)
     total
     (recur (dec start) (or (multiple_of? 3 start) (multiple_of? 5 start)
                            (+ total start) start)))))

我收到以下错误:

java.lang.Boolean cannot be cast to java.lang.Number

我猜它与以下内容有关:

(recur (dec start) (or (multiple_of? 3 start) (multiple_of? 5 start)
                            (+ total start)
                            start)))))

但我不确定为什么,我是 clojure 的新手,所以我想掌握 recur。

一旦 start 是 3 的倍数,您的 or 调用 returns 布尔值 ((multiple_of? 3 start))。

在 Clojure 中,or 总是 returns 它的参数之一 -- 如果存在,则为第一个真值,否则为最后一个假值.

您确实需要 recur 的条件表达式,并且总是 returns 一个数字。例如:

(defn sum_of_multiples_from
  ([start] (sum_of_multiples_from start 0))
  ([start total]
    (if (<= start 0)
      total
      (recur (dec start)
         (if  (or (multiple_of? 3 start) (multiple_of? 5 start))
           (+ total start)
           total)))))

请注意,这是一种用函数式语言实现它的奇怪方式。您实际上是从一个范围中选择值并将它们相加,因此最好将其实现为过滤器和减少,例如:

(reduce + (filter #(or (multiple_of? 3 %) (multiple_of? 5 %)) (range 50)))
=> 543