Clojure 线程优先宏 (->) 与线程最后宏 (->>) 有哪些实际差异?

Git*_*ush 4 clojure

->我仍然不完全理解两个 Clojure 箭头宏 thread-first和 thread-last 宏之间的区别->>。在阅读https://clojure.org/guides/threading_macros时,我了解到线程优先 ->是单个对象上嵌套操作的替代表达式,每个数据步骤都使用该对象作为输入参数,执行独立的操作。

(defn transformation [object]
  (transform2 (transform1 object)))
Run Code Online (Sandbox Code Playgroud)

变成

(defn transformation [object]
  (-> object
      (transform1)      ;; object as implicit argument
      (transform2)))    ;; object as implicit argument 
Run Code Online (Sandbox Code Playgroud)

当使用威胁最后->>运算符时,每个转换都使用前面转换的输出作为隐式参数:

(defn transformation [object]
  (->> object
       (transform1)      ;; object as implicit argument
       (transform2)))    ;; (transform1 object) as implicit argument
Run Code Online (Sandbox Code Playgroud)

这些差异有什么实际意义?我知道使用威胁优先->对地图和字典进行操作是有意义的,其中每个转换都会创建原始实例的新副本,必须为下一个操作提供该副本。然而,在许多情况下,两个运算符实际上表现相同:

(->> [2 5 4 1 3 6] (reverse) (rest) (sort) (count)) ;; => 5
(->  [2 5 4 1 3 6] (reverse) (rest) (sort) (count)) ;; => 5
Run Code Online (Sandbox Code Playgroud)

cus*_*der 5

实际的区别在于宏将变量(以及后续结果)“插入”到表达式中的位置:

(ns so.example)

(defn example-1 [s]
  (-> s
      (str "foo")))

(defn example-2 [s]
  (->> s
      (str "foo")))

(example-1 "bar")
;=> "barfoo"

(example-2 "bar")
;=> "foobar"
Run Code Online (Sandbox Code Playgroud)

所以(-> "bar" (str "foo"))与 相同 且(str "bar" "foo")(->> "bar" (str "foo"))相同(str "foo" "bar")。使用一元函数->->>同样的事情。

当您需要更灵活地确定应在何处插入这些结果时,您可以使用as->

(ns so.example)

(defn example-3 [s]
  (as-> s v
      (str "foo" v "foo")))

(example-3 "bar")
;=> "foobarfoo"
Run Code Online (Sandbox Code Playgroud)

  • @GitCrush或换句话说:对于单参数函数,“线程优先”和“-last”的“第一个”和“最后一个”参数是相同的参数位置。 (2认同)
  • @customcommander你的例子太小/太简单,无法真正说明为什么 as-> 存在。您的三个示例函数确实太小/太简单,甚至不需要 -> 或 ->>。as-> 背后的想法是,它可以在由 -> 线程化的函数管道中间使用,以便将值放置在 as-> 的第一个参数处,并且您提供将该值绑定到的符号,仅适用于管道中的一个槽,您需要在多个位置或非第一个(或非最后一个)位置使用该值。很难用简短的评论来解释,但希望这能澄清预期的用途? (2认同)