繁体   English   中英

Clojure错误(未绑定fn)

[英]Error on Clojure (unbound fn)

我开始从头开始学习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))

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

(->> (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))

上面两个都产生相同的答案。

这是使用更多功能样式的轮廓。 当然,有多种方法可以做到这一点(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中的值通常是不可变的)。 如果要使用可变的Java变量,则必须使用atom

(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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM