【问题标题】:Why does the execution order of tasks in clojure boot change?为什么clojure boot中任务的执行顺序会发生变化?
【发布时间】:2016-04-17 06:58:34
【问题描述】:
(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,执行顺序是从右到左。这种不一致如何合理?

【问题讨论】:

    标签: clojure function-composition boot-clj


    【解决方案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 后调用它)。

    您可以在its wiki 中阅读有关启动任务剖析的更多信息。阅读ring middleware 可能也很有用。

    【讨论】:

    • 谢谢!你的解释很好!
    • 你会修改你的答案以“这是执行顺序”开头吗?我仍然不确定,但我认为(comp (task1) (task2)) 意味着(task1 (task2))
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-18
    • 2022-01-13
    • 2020-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多