Clojure线程宏

Clojure线程宏,clojure,Clojure,我不确定这是不是最好的发帖地点,但为什么不行呢?线程宏没有将seq的结果传递到(map str) 您使用的是宏,它将每个表单作为下一个表单的第二项插入,如下所示: (-> (* x y) str seq (map str)) (-> (str (* x y)) seq (map str)) (-> (seq (str (* x y))) (map str)) (map (seq (str (* x y))) str) 您需要的是宏: 正如Elogent指出的那样,宏将参数放在

我不确定这是不是最好的发帖地点,但为什么不行呢?线程宏没有将seq的结果传递到
(map str)

您使用的是宏,它将每个表单作为下一个表单的第二项插入,如下所示:

(-> (* x y) str seq (map str))
(-> (str (* x y)) seq (map str))
(-> (seq (str (* x y))) (map str))
(map (seq (str (* x y))) str)
您需要的是宏:


正如Elogent指出的那样,宏将参数放在了错误的位置。一般来说,在使用宏(尤其是编写宏)时,了解
macroexpand-1
并将其与
clojure.pprint/pprint
相结合有助于了解实际运行的内容:

user> (clojure.pprint/pprint
       (macroexpand-1
        '(-> (* x y)
             str
             seq
             (map str))))
(map (seq (str (* x y))) str)
nil
我们可以看到它看起来不太正确。因此,接下来我们将对其进行处理,直到它扩展到我们所期望的:

user> (clojure.pprint/pprint
       (macroexpand-1
        '(->> (* x y)
              str
              seq
              (map str))))
(map str (seq (str (* x y))))
nil
有多种线程宏可帮助处理此类情况,尤其是
as->
,当您需要使用重要输入的第一个和最后一个参数对函数执行线程时,可以为线程值指定一个显式名称:

user> (as-> (* 7 42) x
        (str x)
        (seq x)
        (map str x))
("2" "9" "4")

这里有一个很好的选择(从右到左阅读):


这可能在您想将转换应用到应用程序的上下文中有用(我欢迎受此主题的P<)的批评。您也可以考虑使用<代码> IT > >代码>线程窗体,这是为了避免线程第一次对线程最后的担忧。请考虑此代码:

(ns clj.core
  (:use tupelo.core))

(defn a [x y]
  (it-> (* x y)
      (str it)
      (seq it)
      (map str it)))

(spyx (a 8 8))

(defn -main [] )
产生:

(a 8 8) => ("6" "4")

it->
宏使用占位符
it
显式地选择每个后续表单的结果放置位置。这是简化代码和避免此类错误的一种简单方法。

您的意图是好的,但由于您已经将转换和数据组合到
a
函数中,因此无法实现我会从这个方法中得到任何东西。谢谢你的建议。它看起来像一个非常可爱的图书馆。
(defn a [x y]
  ((comp (partial map str) seq str *)
    x y))
(ns clj.core
  (:use tupelo.core))

(defn a [x y]
  (it-> (* x y)
      (str it)
      (seq it)
      (map str it)))

(spyx (a 8 8))

(defn -main [] )
(a 8 8) => ("6" "4")