【问题标题】:Create a clojure map threading macro ( map-> )创建一个 clojure 映射线程宏( map-> )
【发布时间】:2013-01-10 00:20:10
【问题描述】:

我的灵感来自clojure's 1.5 cond-> macro.

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

例如,我找不到cond-> 的来源。 (可能还没有发布)

有什么建议吗?

【问题讨论】:

  • 你能解释一下“同样的想法,应用于函数map”吗?
  • @mobyte 与使用map 作为一系列语句中的函数相同的想法,目的是使代码可读。
  • 你能举个例子吗?

标签: clojure


【解决方案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))

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

【讨论】:

    【解决方案3】:

    如果我理解——你想编写一个宏,它接受一个部分函数调用的列表,并为每个调用添加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 他们是一个很好的介绍。

    【讨论】:

      猜你喜欢
      • 2020-07-23
      • 1970-01-01
      • 2013-10-09
      • 1970-01-01
      • 2012-09-07
      • 1970-01-01
      • 1970-01-01
      • 2019-09-08
      • 1970-01-01
      相关资源
      最近更新 更多