2012-02-09 80 views
6

例如,解决了以下问题在Clojure中,是否可以在匿名函数中定义一个匿名函数?

http://projecteuler.net/problem=5

我想出了以下解决方案

(defn div [n] (= 0 (reduce + (map #(mod n %) (range 1 21))))) 
(take 1 (filter #(= true (div %)) (range 20 1e11 20))) 

假设一些高尔夫的乐趣我想的第一行合并为一个匿名函数进第二行。语言是否支持这个?

+0

您可以以更有效的方式重写您的解决方案。请参阅下面的答案。 – viebel 2012-02-09 20:57:07

回答

17

是的,但不能嵌套#()阅读器宏表单,您必须使用(fn)表单。

例如:

(#(#(+ %1 %2) 1) 2) 

不起作用,因为没有办法提及的外匿名函数的参数。这被认为是带有两个参数的外部函数,而内部函数是零参数。

但是你可以用(fn...)写点什么同样的事情:

user=> (((fn [x] (fn [y] (+ x y))) 1) 2) 
3 

您也可以使用#()形式的两个匿名的功能之一,例如:

user=> (#((fn [x] (+ x %)) 1) 2) 
3 

所以,你可以内嵌你的div函数是这样的(请注意,我们必须将#()表单传递给map转换为(fn)表单):

#(= true (= 0 (reduce + (map (fn [x] (mod % x)) (range 1 21))))) 
+7

作为一个经验法则:'fn'是定义匿名函数的语法,而不是'#()'。 '#()'只是简单函数调用的便利,比如'#(mod%x)',其中'fn'会增加很多噪音。对于具有更长主体的功能'fn'应该是优选的。 – kotarak 2012-02-09 12:23:46

0

你可以在一个更简单,更有效的方式重写你的解决方案(X2更快!)

(defn div [n] (every? #(= 0 (mod n %)) (range 1 21))) 
(take 1 (filter div (range 20 1e11 20))) 

的原因,它是更有效的是因为every?不会遍历整个列表,而是停当列表中的某个元素为假时。

+0

或者你可以通过完全避免蛮力来解决它大约10倍的速度。 。 。 – ruakh 2012-02-09 21:14:43

+0

确实。但我正在考虑任何clojure相关的改进,而不是数学上的改进。 – viebel 2012-02-09 21:36:04