Передача данных через произвольные функции в Clojure - PullRequest
16 голосов
/ 10 сентября 2010

Я знаю, что форму -> можно использовать для передачи результатов одного результата функции другому:

(f1 (f2 (f3 x))) 
(-> x f3 f2 f1) ; equivalent to the line above

(взято из превосходного учебника по Clojure в ociweb )

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

Я написал эту функцию зацикливания, которая делает это, но у меня есть ощущение, что есть лучший способ:

(defn pipe [initialData, functions]
  (loop [
      frontFunc (first functions)
      restFuncs (rest functions)
      data initialData ]
    (if frontFunc
      (recur (first restFuncs) (rest restFuncs) (frontFunc data) )
      data )
  ) )

Как лучше всего это сделать?

Ответы [ 3 ]

20 голосов
/ 10 сентября 2010

Я должен признать, что я действительно новичок в clojure, и я мог бы здесь упустить момент, но разве это не может быть сделано просто с помощью comp и apply?

user> (defn fn1 [x] (+ 2 x))
user> (defn fn2 [x] (/ x 3))
user> (defn fn3 [x] (* 1.2 x))
user> (defn pipe [initial-data my-functions] ((apply comp my-functions) initial-data))
user> (pipe 2 [fn1 fn2 fn3])
2.8
6 голосов
/ 10 сентября 2010

Вы можете сделать это с простым старым reduce:

(defn pipe [x fs] (reduce (fn [acc f] (f acc)) x fs))

, который можно сократить до:

(defn pipe [x fs] (reduce #(%2 %1) x fs))

Используется так:

user> (pipe [1 2 3] [#(conj % 77) rest reverse (partial map inc) vec])
[78 4 3]
4 голосов
/ 10 сентября 2010

Если функции - это последовательность функций, вы можете уменьшить ее, используя comp, чтобы получить составную функцию. При ответе:

user> (def functions (list #(* % 5) #(+ % 1) #(/ % 3)))
#'user/my-list
user> ((reduce comp functions) 9)
20

apply также работает в этом случае, потому что comp принимает переменное число аргументов:

user> (def functions (list #(* % 5) #(+ % 1) #(/ % 3)))
#'user/my-list
user> ((apply comp functions) 9)
20
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...