创建一个Clojure的Map线程宏(map->)

3
我受到Clojure 1.5中的cond->宏的启发。
同样地,我想创建一个类似的宏,应用于函数map。 然而,我不知道从哪里开始。
例如,我找不到cond->的源代码。(可能是因为它还没有发布)
有什么建议吗?

你能解释一下“相同的想法,应用于函数map”吗? - mobyte
使用map作为函数在一系列语句中的目的是使代码更易读,可以说是“同样的想法”。 - Zchpyvr
1
你能举个使用的例子吗? - mobyte
3个回答

3

谢谢你提供的参考!现在看来,首先在那里寻找它似乎很明显。 - Zchpyvr

2
这里有来自 Pallet 项目团队的各种线程宏,包括 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
如果我理解正确 -- 你想编写一个宏,接收部分函数调用的列表,然后对于每一个调用,在开头添加map(或apply map),并将先前的结果添加到末尾?
虽然这并没有直接回答如何编写该宏,但我想指出你有几个替代方案。

因式分解map

对于纯函数,这总是成立:
(=
  (map g (map f coll))
  (map (comp g f) coll))

重构后的版本只需一次遍历集合,不需要创建中间集合。

以下是使用线程的示例:

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

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

转换器

转换器是Clojure中用于处理不仅仅是map的一种模式。它们可以看作是对缩减函数的一种抽象。如果在没有集合的情况下调用Clojure的map/filter/reduce(等等),将创建一个转换器。您可以使用comp链接它们并在各种上下文(惰性、急切、可观察等)中使用它们。Rich Hickey的演讲是一个很好的入门指南。

这里有一个JS的具体示例。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接