Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Clojure-总结一组数字_Clojure_Lisp - Fatal编程技术网

Clojure-总结一组数字

Clojure-总结一组数字,clojure,lisp,Clojure,Lisp,嘿,我在做一个Euler项目的问题,我想把1000以下的所有数字加起来,它们是3或5的倍数 但是作为一个clojure noob,我的代码总是返回零。。我不知道为什么 (defn sum-of-multiples [max] (let [result (atom 0)] (for [i (range max)] (if (or (= (rem i 3) 0) (= (rem i 5) 0)) (swap! result (+ @result i)))

嘿,我在做一个Euler项目的问题,我想把1000以下的所有数字加起来,它们是3或5的倍数

但是作为一个clojure noob,我的代码总是返回零。。我不知道为什么

(defn sum-of-multiples [max]
  (let [result (atom 0)]
    (for [i (range max)] 
      (if (or (= (rem i 3) 0) (= (rem i 5) 0))
        (swap! result (+ @result i)))    
      )
    @result))

(sum-of-multiples 1000)
还有一行
(swap!result(+@result i))
让我感到不舒服。。在C#中,我可以做
result+=I
,但我猜在Clojure中肯定有更好的方法来实现这一点?

是一种返回惰性序列的列表理解,您必须遍历它才能使代码正常工作:

(定义倍数之和[max]
(让[结果(原子0)]
(多伦
(对于[i(最大范围)]
(如果(或(=(rem i 3)0)(=(rem i 5)0))
(交换!结果+i)))
@结果)

使用for的一种等效的、更惯用的实现:

(定义倍数之和[max]
(减少+
(适用于[i(最大范围)
:何时(或(零?(rem i 3))
(零?(rem i 5))]
i) ))

在Clojure中,以及在函数式编程中,我们避免赋值,因为赋值会破坏状态历史,并使编写并发程序变得更加困难。事实上,Clojure甚至不支持赋值。原子是线程安全的引用类型

函数式编程的另一个共同特点是,我们试图通过一系列数据转换来解决问题。在您的例子中,您需要对一些数据进行装箱,一个从0到1000的数字列表,并且您需要获得与谓词匹配的所有数字的总和。这当然可以通过应用数据转换和完全消除赋值的需要来实现。其中一项实施是:

(->> (range 1000)
     (filter #(or (= (rem % 3) 0) (= (rem % 5) 0)))
     (reduce +))
请理解,您编写的函数不被视为惯用代码。话虽如此,为了学习的利益,可以这样做:

(defn sum-of-multiples [max]
  (let [result (atom 0)]
    (doseq [i (range max)] 
      (if (or (= (rem i 3) 0) (= (rem i 5) 0))
        (swap! result #(+ % i)))    
      )
    @result))

(sum-of-multiples 1000)

for
返回一个延迟序列,但因为您只是对
交换引起的副作用感兴趣
您需要使用
doseq
强制执行序列。另一个问题是
swap!的第二个参数
是一个函数,因此您无需再次定义
结果。

其他答案就是我在评论中提到的很好的例子。为了完整性起见,这里有一个使用
循环/重现
的解决方案,因此对于那些仍然不熟悉过滤器、映射或减少等概念的人来说,它可能更容易理解。它也恰好快了30-40%,在这种情况下这并不重要

(defn sum-of-multiples [max]
  (loop [i 0
         sum 0]
    (if (> max i)
       (recur (inc i)
              (if (or (zero? (rem i 3)) (zero? (rem i 5)))
                (+ sum  i)
                sum))
        sum)))

你的代码有很多地方是错误的。首先,
For
不是一个循环,而是一个惰性序列(请参见
doseq
)。此外,您的掉期声明是错误的。您需要
(swap!result+i)
。最后,您不需要州政府来做这件事。你应该以一种纯粹的功能性方式进行,而不使用doseq或atoms。
(swap!result#(+%i))
(swap!result+i)
是的。它们是等价的。我把它保存在匿名函数符号中,所以它接近OP的值。开枪!出于这个确切的原因,我在谷歌上搜索了如何求和,并得到了完整的Euler 1答案:谢天谢地,我以前实现过它。非常简洁的回答!