Clojure中的广义线程宏

时间:2012-04-09 02:50:53

标签: macros clojure

注意:这不是关于并发性的。这是关于线程宏。

我知道->将对象放在第二个位置,->>将参数放在最后一个位置。

现在,我很好奇,就像函数的#( ... % )的简写符号一样,是否有一个简短的线程表示法让我将参数放在任意位置?

目标是不是让线程有一个固定的位置来运行...我可以编写任意形式,并在特殊位置插入%%,%%是插入线程的位置。

谢谢!

4 个答案:

答案 0 :(得分:34)

现在在Clojure中有一个广义的线程宏,从1.5开始称为as->

此推文举例说明了它的工作原理:https://twitter.com/borkdude/status/302881431649128448

(as-> "/tmp" x
      (java.io.File. x)
      (file-seq x)
      (filter (memfn isDirectory) x)
      (count x))

首先'x'绑定到“/ tmp”并从中生成一个文件。 'x'再次反弹到生成的文件,并通过'file-seq'函数等等。

答案 1 :(得分:26)

来自Swiss Arrows图书馆的'钻石魔杖'可以满足您的需求:

(-<> 0
 (* <> 5)
 (vector 1 2 <> 3 4))
; => [1 2 0 3 4]

那就是说,这不是你经常需要的(或者曾经在我的Clojure体验中)

答案 2 :(得分:15)

如果有其他人遇到这个问题,那么提供的宏存在一个原因,但是任意放置的宏都没有:后者会导致API设计不佳。

->宏将参数放在第一个位置。这对应于处理某些主题论证的函数,例如conjassoc

->>宏将参数放在最后一个位置。这对应于处理序列的函数,例如mapreduce

很好地设计你的API,你不太可能需要这样的宏。

答案 3 :(得分:2)

有一个图书馆提供了这个功能,但我忘了在哪里。它可能是在弃用的clojure-contrib中。它是-$>宏。

但你可以从clojure的核心-> macro派生出一个来制作你正在寻找的那个:

(defmacro -$>
    ([x] x)
    ([x form] (if (seq? form)
                (with-meta (map #(if (= %1 '$) x %1) form) (meta form))
                (list form x)))
    ([x form & more] `(-$> (-$> ~x ~form) ~@more)))

并使用$表示插入点:

user=> (-$> 2 str (identity $) (println $))
2
nil

从技术上讲,您可以在一种形式中使用多个$。但是这种实现方式多次扩展相同的形式(换句简单)。