了解复发

时间:2015-07-11 02:28:06

标签: clojure tail-recursion

试用这段代码,似乎没有正常工作..

(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不能转换为java.lang.Number

我猜这与它有关:

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

但是我不确定为什么,我是新手,所以我试图掌握复发。

2 个答案:

答案 0 :(得分:4)

你真的想要recur的条件表达式,并且总是返回一个数字。例如:

(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

答案 1 :(得分:3)

只要start为3的倍数,您的or调用就会返回布尔值((multiple_of? 3 start))。

在Clojure中,or总是返回其中一个参数 - 要么是第一个存在的,要么是最后的错误,否则就是最后的错误。