Clojure错误(未绑定的fn)

时间:2016-11-04 18:59:05

标签: clojure

我开始从头开始学习Clojure并且我坚持我的功能。我试图找到低于1000的3或5的所有倍数的总和。这就是我所做的。

(defn suma [x sum]
     (cond
       (= (/ x 3) 0)(let [sum (+ sum x)])
       (= (/ x 5) 0)(let [sum (+ sum x)])))   

(defn main[]
  (def sum 0)
  (def x 3)
  (while(< x 1001)
    (do
      (suma sum x)
      (let [x (+ x 1)]))
  (str "Total = " sum)))

我尝试了几件事,但我无法弄清楚是什么错...... 任何帮助都会被贬低。

由于

编辑:

已修复,问题出在let,它没有更新数据的值。这是解决方案:

(defn suma [x sum]
     (cond 
     (zero? (mod x 3))(alter-var-root #'sum (constantly (+ sum x)))
     (zero? (mod x 5))(alter-var-root #'sum (constantly (+ sum x)))))

(defn main[]
  (def sum 0)
  (def x 3)
  (while(< x 1001)
    (do
      (suma x sum)
      (alter-var-root #'x inc)))
      (str "TOTAL = " sum))

2 个答案:

答案 0 :(得分:2)

使用序列库的简单解决方案是

(->> (concat
      (range 0 1000 3)
      (range 0 1000 5))
     distinct
     (apply +))

如果您想以迭代方式进行,请不要使用while,这取决于副作用。使用looprecur,它会影响一种称为尾递归的原始递归形式:

(defn divides? [i j]
  (zero? (mod j i)))

(loop [answer 0, n 0]
  (if (< n 1000)
    (recur
     (if (or (divides? 3 n) (divides? 5 n))
       (+ answer n)
       answer)
     (inc n))
    answer))

以上两者都产生了相同的答案。

答案 1 :(得分:1)

这是使用更多功能样式的大纲。当然,有不止一种方法可以做到这一点(TM)。 :)

> lein repl

user=> (def data (range 20))
user=> data
(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19)

user=> (defn is-mul-3? [x] (zero? (mod x 3)))
user=> (mapv is-mul-3? data)
[true false false true false false true false false true false false true false false true false false true false]

user=> (defn is-mul-5? [x] (zero? (mod x 5)))
user=> (mapv is-mul-5? data)
[true false false false false true false false false false true false false false false true false false false false]

user=> (defn is-mul-3-or-5? [x] (or (is-mul-3? x) (is-mul-5? x)))
user=> (mapv is-mul-3-or-5? data)
[true false false true false true true false false true true false true false false true false false true false]

user=> (def only-3s-and-5s (filterv is-mul-3-or-5? data))
user=> only-3s-and-5s
[0 3 5 6 9 10 12 15 18]

user=> (apply + only-3s-and-5s)
78

更新

这是一个更加不完美的版本。 Clojure值(如let中的值通常是不可变的)。如果你想要一个类似的东西,你必须使用atom 可变的Java变量:

(ns clj.core
  (:gen-class))

(defn is-mul-3? [x] 
  (zero? (mod x 3)))

(defn is-mul-5? [x] 
  (zero? (mod x 5)))

(defn is-mul-3-or-5? [x] 
  (or (is-mul-3? x) 
      (is-mul-5? x)))

(defn sum-3s-and-5s [limit]
  (let [cum-sum (atom 0) ]
    (doseq [curr-val (range limit)]
      (if (is-mul-3-or-5? curr-val)
        (swap! cum-sum + curr-val)))
    @cum-sum ))

(defn -main [& args]
  (println "cumsum = " (sum-3s-and-5s 20))
)

结果:

~/clj > lein run
cumsum =  78