6

I wanted to do this:

(-> string
    (str/split "\s")
    (modification-1)
    (modification-2)
    …
    (modification-n
    (str/join "\n"))

But no, split takes [s regex] and join takes [seperator coll].

Is there any apparent reason for this madness (read: What is the design decision behind this)?

4

4 回答 4

8

从 Clojure 1.5 开始,您还可以使用新的线程宏之一。

clojure.core/as->

([expr name & forms])

将 name 绑定到 expr,计算该绑定的词法上下文中的第一个表单,然后将 name 绑定到该结果,对每个后续表单重复,返回最后一个表单的结果。

这是一个相当新的结构,所以还不知道如何习惯性地使用,但我想这样的事情会做:

(as-> "test test test" s
    (str/split s #" ")
    (modification-1 s)
    (modification-2 s)
    ...
    (modification-n s)
    (str/join "\n" s))

编辑

至于为什么论点立场不同,我无处可说,但我认为亚瑟的建议是有道理的:

  • 一些函数显然对集合(map、、reduce等)进行操作。这些倾向于始终将集合作为最后一个参数,这意味着它们可以很好地与->>
  • 有些函数不对集合进行操作,并且倾向于将最重要的参数(这是一件事吗?)作为第一个参数。例如,在使用时,/我们希望分子排在第一位。这些功能最适用于->

问题是 - 有些功能是模棱两可的。他们可能会获取一个集合并生成一个值,或者获取一个值并生成一个集合。string\split是一个例子(暂时忽略字符串可能被认为是单个值集合的额外混淆)。串联/减少操作也可以做到——它们会弄乱你的管道!

例如,考虑:

(->> (range 1 5)
     (map inc)
     (reduce +)
     ;; at this point we have a single value and might want to...
     (- 4)
     (/ 2))
     ;; but we're threading in the last position
     ;; and unless we're very careful, we'll misread this arithmetic

在这些情况下,我认为类似的东西as->真的很有帮助。

我认为总的来说,->>在对集合进行操作时使用的指导方针->是合理的——只是在这些边界/模棱两可的情况下,as->可以使代码更整洁、更清晰。

于 2013-08-14T15:56:06.420 回答
2

您可以使用部分函数来修复 str/join 的分隔符参数。

(-> string
  (str/split #"\s")
  (modification-1)
  (modification-2)
  ;;
  (modification-n)
  ((partial str/join "\n")))
于 2013-08-14T14:56:47.017 回答
2

我也经常遇到这种(轻微的)线程头痛。

(-> string
    (str/split "\s")
    (modification-1)
    (modification-2)
    …
    (modification-n
    (#(str/join "\n" %)))

并且经常创建一个匿名函数来进行排序匹配。我的猜测是为什么某些函数打算与 thread first 一起使用->,一些用于 thread last->>和一些 threading 不是设计目标,尽管这只是一个猜测。

于 2013-08-14T14:58:35.400 回答
1

通过另一个线程宏对线程表达式进行线程化并没有错,如下所示:

(-> string
    (str/split "\s")
    modification-1
    modification-2
    modification-n
    (->> (str/join "\n")))
于 2013-08-15T13:37:01.987 回答