3

我受到clojure 的 1.5cond->宏的启发。

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

例如,我找不到cond->. (可能是因为还没有发布)

有什么建议么?

4

3 回答 3

3

cond-> https://github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj#L6742的来源

于 2013-01-10T01:33:55.720 回答
2

托盘项目人员提供了各种线程宏,包括 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))

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

于 2013-01-10T02:01:24.370 回答
2

如果我理解 - 你想编写一个宏,它需要一个部分函数调用的列表,并且对于每个函数,在开头添加map(或apply map),并将前一个结果添加到结尾?

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

分解出map

对于纯函数来说总是如此:

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

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

这是线程的样子:

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

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

这是 JS 中的一个具体示例。

传感器

转换器是在 Clojure 中做这种事情的另一种模式,它不仅仅适用于map. 它们是对 reducer 函数的一种抽象。如果在没有集合的情况下调用Clojure 的map// filter(等),将创建一个转换器。reduce您可以将它们链接起来comp并在各种上下文中使用它们(懒惰的、渴望的、可观察的,等等)。Rich Hickey关于它们的演讲是一个很好的介绍。

于 2019-04-24T19:30:26.387 回答