Почему меняется порядок выполнения задач в clojure при загрузке?
(deftask test1 "first test task" [] (print "1") identity)
(deftask test2 "second test task" [] (print "2") identity)
(boot (comp (test1) (test2)))
=> 12nil
(boot (comp (fn [x] (print "1") identity) (fn [x] (print "2") identity)))
=> 21nil
Если я использую comp
в задачах порядок выполнения слева направо. Если я использую comp
в анонимных функциях порядок выполнения справа налево. Насколько это противоречие разумно?
1 ответ
Причина этой разницы в том, что когда вы используете comp
с загрузочными задачами то, что они не являются простой логикой, которая составляется, но каждая загрузочная задача возвращает функцию, которая будет вызвана позже, и эта функция оборачивает другую функцию, которая передается ему (как в промежуточном программном обеспечении кольца).
С простыми функциями это работает так:
(comp inc dec)
производит функцию, которая делает следующее:
(inc (dec n))
В загрузке задачи похожи на кольцевое промежуточное ПО. Каждая задача - это функция, которая возвращает другую функцию, которая обернет следующий обработчик из конвейера. Это работает так (не буквально, это упрощено для удобства чтения):
(defn task1 []
(fn [next-handler]
(fn [fileset]
(print 1) ;; do something in task1
(next-handler fileset))) ;; and call wrapped handler
(defn task2 []
(fn [next-handler]
(fn [fileset]
(print 2) ;; do something in task1
(next-handler fileset)))) ;; and call wrapped handler
Итак, когда вы делаете:
(comp (task1) (task2))
И выполнить такую сложную задачу, она работает так, как будто это было:
(fn [fileset1]
(print 1)
((fn [fileset2]
(print 2)
(next-handler fileset2))
fileset1))
Потому что функция производит (task2)
будет передан функции, произведенной (task1)
который обернет тот из (task2)
(и позвоните после печати 1
).
Вы можете прочитать больше об анатомии загрузочных задач в вики. Это также может быть полезно для чтения промежуточного программного обеспечения.