Можно ли в Clojure определить анонимную функцию внутри анонимной функции? - PullRequest
6 голосов
/ 09 февраля 2012

Например, для решения следующей задачи

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

Предположим, что для игры в гольф я хочу объединитьсяпервая строка как анонимная функция во вторую строку.Поддерживает ли язык это?

Ответы [ 2 ]

17 голосов
/ 09 февраля 2012

Да, это так, но вы не можете вкладывать формы #() читатель-макрос, вам нужно использовать форму (fn).

Например:

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

неработать, потому что нет способа ссылаться на аргументы внешних анонимных функций.Это читается как внешняя функция, принимающая два аргумента, и внутренняя функция, принимающая нулевые аргументы.

Но вы можете написать то же самое с помощью (fn...) s:

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)))))
0 голосов
/ 10 февраля 2012

Вы можете переписать свое решение намного проще и эффективнее (в 2 раза быстрее!)

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

Причина, по которой он более эффективен, заключается в том, что every? не будет проходить по всему списку, а остановится, если один из элементов списка будет ложным.

...