创建一个clojure贴图线程宏(map->)

时间:2013-01-10 00:20:11

标签: clojure

我受到clojure's 1.5 cond-> macro.

的启发

类似地,我想创建一个同样想法的宏,应用于函数map。但是,我不知道从哪里开始。

例如,我找不到cond->的来源。 (可能是因为它尚未发布)

有什么建议吗?

3 个答案:

答案 0 :(得分:3)

答案 1 :(得分:2)

来自托盘项目人员的各种threading macros包括apply-map->看起来很接近,虽然不是你想要的。

(letfn [(apply-map-
          [arg f arg-coll]
          `(let [arg# ~arg]
             (apply ~f arg#
                    ~@(butlast arg-coll)
                    (apply concat ~(last arg-coll)))))]

  (defmacro apply-map->
    "Apply in a threaded expression.
   e.g.
      (-> :a
        (apply-map-> hash-map 1 {:b 2}))
   => {:a 1 :b 2}"
    [arg f & arg-coll]
    (apply-map- arg f arg-coll))

也许会有足够的例子让你挑选出你需要的东西。

答案 2 :(得分:1)

如果我理解-您想编写一个宏,其中包含部分函数调用的列表,并为每个宏添加map(或apply map)到开头以及前一个结果到底?

虽然这不能直接回答如何编写该宏,但我想指出您有几种选择。

因素出map

对于纯函数总是如此:

(=
  (map g (map f coll))
  (map (comp g f) coll))

重构后的版本只遍历一次集合,而无需进行任何中间集合。

这是线程的样子:

(=
  (->> coll
       (map f)
       (map g))

  (map #(->> % f g) coll))

Here's a concrete example in JS.

换能器

Transducers是Clojure中执行此类操作的另一种模式,其作用不仅限于map。它们是对reducer函数的抽象。如果在没有集合的情况下调用Clojure的map / filter / reduce(等等),则会创建一个转换器。您可以将它们与comp链接起来,并在各种上下文中使用它们(懒惰,渴望,可观察,等等)。 Rich Hickey's talk是一个很好的介绍。