我阅读了很多关于 Clojure 的文档(并且需要再次阅读)并阅读了关于 SO 的几个 Clojure 问题,以获得对语言的“感觉”。除了 elisp 中的一些小函数之外,我以前从未用任何 Lisp 语言编写过。我在 Clojure 中编写了我的第一个项目 Euler 解决方案,在继续深入之前,我想更好地了解有关map和reduce的一些知识。
使用 lambda,我最终得到以下结果(将 3 或 5 或两者的所有倍数相加在 1 到 1000 之间):
(reduce + (map #(if (or (= 0 (mod %1 3)) (= 0 (mod %1 5))) %1 0) (range 1 1000)))
我把它放在一行是因为我把它写在 REPL 上(它给出了正确的解决方案)。
没有 lambda,我写了这个:
(defn val [x] (if (or (= 0 (mod x 3)) (= 0 (mod x 5))) x 0))
然后我计算这样做的解决方案:
(reduce + (map val (range 1 1000)))
在这两种情况下,我的问题都涉及在执行reduce之前地图应该返回什么。完成地图后,我注意到我最终得到了一个如下所示的列表:(0 0 3 0 5 6 ...)。
我尝试删除val定义末尾的“0”,但随后我收到了一个由(nil nil 3 nil 5 6 etc.)组成的列表。我不知道nil是否有问题。我发现无论如何我都会在进行左折叠时进行求和,这样零就不是真正的问题了。
但是仍然:返回的合理地图是什么?(0 0 3 0 5 6 ...) 或 (nil nil 3 nil 5 6...) 或 (3 5 6 ...) (我将如何处理最后一个?)或其他什么?
我应该“过滤掉”零点/零点吗?如果是的话怎么办?
我知道我在问一个基本问题,但 map/reduce 显然是我会经常使用的东西,所以欢迎任何帮助。