我不确定这是发布的最佳位置,但为什么不能发挥作用?线程宏没有将seq的结果传递给(map str)
吗?
;; 1
(map str (seq (str (* 8 8)))) -> ("6" "4")
;; 2
(defn a [x y]
(-> (* x y)
str
seq
(map str)))
(a 8 8) -> Don't know how to create ISeq from: clojure.core$str
答案 0 :(得分:6)
您正在使用thread-first宏,它将每个表单作为下一个项目的第二项插入,如下所示:
(-> (* x y) str seq (map str))
(-> (str (* x y)) seq (map str))
(-> (seq (str (* x y))) (map str))
(map (seq (str (* x y))) str)
你想要的是thread-last宏:
(defn a [x y]
(->> (* x y) str seq (map str)))
(a 8 8) ;=> ("6" "4")
答案 1 :(得分:4)
正如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")
答案 2 :(得分:1)
这是一个很好的选择(从右到左阅读):
(defn a [x y]
((comp (partial map str) seq str *)
x y))
这可能在您要将要应用的转换与应用的数据分开的上下文中有用(我欢迎批评该主题)。
答案 3 :(得分:1)