为什么clojure引导中任务的执行顺序会发生变化?

Xia*_*ian 1 clojure function-composition boot-clj

(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
Run Code Online (Sandbox Code Playgroud)

如果我使用comp任务,执行顺序是从左到右.如果我使用comp匿名函数,则执行顺序是从右到左.这种不一致性如何合理?

Pio*_*dyl 6

造成这种差异的原因是,当您使用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
Run Code Online (Sandbox Code Playgroud)

所以当你这样做时:

(comp (task1) (task2))

并执行这样的组合任务,就好像它是:

(fn [fileset1]
  (print 1)
  ((fn [fileset2]
     (print 2)
     (next-handler fileset2))
   fileset1))
Run Code Online (Sandbox Code Playgroud)

因为生成的函数(task2)将被传递给生成的函数,(task1)该函数将从中包装(task2)(并在打印后调用它1).

您可以在其wiki中阅读有关启动任务解剖的更多信息.阅读环中间件可能也很有用.