2013-03-14 16 views
6

Mam funkcję, którą zasadniczo wyciągnąłem z dyskusji w grupie Clojure google, która pobiera kolekcję i listę funkcji o dowolnej długości, i filtruje ją, aby zwrócić nową kolekcję zawierającą wszystkie elementy oryginalnej listy, dla której w najmniej jedną z funkcji jest true:Aplikacja Clojure Partial - jak uzyskać "mapę", aby zwrócić kolekcję funkcji?

(defn multi-any-filter [coll & funcs] 
    (filter #(some true? ((apply juxt funcs) %)) coll)) 

gram około z podejmowania uogólnionego rozwiązania Project Euler Problem 1, więc używam go tak:

(def f3 (fn [x] (= 0 (mod x 3)))) 
(def f5 (fn [x] (= 0 (mod x 5)))) 

(reduce + (multi-any-filter (range 1 1000) f3 f5)) 

co daje poprawną odpowiedź .

Jednak chce zmodyfikować tak, że może przechodzić ints niej zamiast funkcji jak

(reduce + (multi-any-filter (range 1 1000) 3 5)) 

których można wymienić: 3 i 5, za pomocą dowolnej liczby wskazówki i do owijania funkcję (= 0 (mod xy)) jako anonimowa funkcja wewnątrz funkcji multi-any-filter.

Niestety, to przekracza limit mojej zdolności Clojure. Myślę, że będę musiał coś zrobić z map do listy argumentów, ale nie jestem pewien, jak uzyskać map, aby zwrócić listę funkcji, z których każda czeka na inny argument. Clojure nie wydaje się wspierać tego, w jaki sposób nauczyłem się tego w innych językach funkcjonalnych. Być może potrzebuję użyć partial we właściwym miejscu, ale nie jestem całkiem pewien jak.

Innymi słowy, chcę być w stanie przekazać dowolną liczbę argumentów (które nie są funkcjami), a następnie każdy z tych argumentów zostanie zapakowany w tę samą funkcję, a następnie lista funkcji zostanie przekazana do juxt na miejsce funcs w mojej funkcji multi-any-filter powyżej.

Dzięki za wszelkie wskazówki!

Odpowiedz

6
(defn evenly-divisible? [x y] 
    (zero? (mod x y))) 

(defn multi-any-filter [col & nums] 
    (let [partials (map #(fn [x] (evenly-divisible? x %)) nums) 
     f (apply juxt partials)] 
    (filter #(some true? (f %)) col))) 

I coudn't używać partial ponieważ dotyczy ARG w pierwszej pozycji fn. Chcemy go na drugiej pozycji evenly-divisible? Możemy ponownie ustawić w evenly-divisible?, ale wtedy naprawdę nie wyglądałoby poprawnie, gdy używa się go samodzielnie.

user=> (reduce + (multi-any-filter (range 1 1000) 3 5)) 
233168 
+0

Skała, tego właśnie szukałem. – kyllo