为什么clojure boot中任务的执行顺序会发生变化?
Why does the execution order of tasks in clojure boot change?
(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
,执行顺序是从右到左。这种不一致如何合理?
造成这种差异的原因是,当您将 comp
与引导任务一起使用时,它们不是组合的裸逻辑,而是每个引导任务 returns 一个稍后将调用的函数,并且该函数包装了传递给它的另一个函数(就像在环形中间件中一样)。
使用普通函数,它的工作原理如下:
(comp inc dec)
生成一个执行以下操作的函数:
(inc (dec n))
启动任务类似于环中间件。每个任务都是一个函数,returns 另一个函数将包装管道中的下一个处理程序。它是这样工作的(不是字面意思,为了便于阅读而简化):
(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
后调用它) .
您可以在 its wiki. It might be also useful to read on ring middleware 中阅读更多关于引导任务剖析的信息。
(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
,执行顺序是从右到左。这种不一致如何合理?
造成这种差异的原因是,当您将 comp
与引导任务一起使用时,它们不是组合的裸逻辑,而是每个引导任务 returns 一个稍后将调用的函数,并且该函数包装了传递给它的另一个函数(就像在环形中间件中一样)。
使用普通函数,它的工作原理如下:
(comp inc dec)
生成一个执行以下操作的函数:
(inc (dec n))
启动任务类似于环中间件。每个任务都是一个函数,returns 另一个函数将包装管道中的下一个处理程序。它是这样工作的(不是字面意思,为了便于阅读而简化):
(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
后调用它) .
您可以在 its wiki. It might be also useful to read on ring middleware 中阅读更多关于引导任务剖析的信息。