2012-02-09 79 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