【问题标题】:"Updating" a map/data structure in consecutive function calls in Clojure在 Clojure 中的连续函数调用中“更新”映射/数据结构
【发布时间】:2015-03-24 13:55:07
【问题描述】:

我想在 Clojure 中通过多次调用函数来“更新”地图。思路如下:

(defn foo1
  [a-map]
  (assoc a-map :key1 "value1"))

(defn foo2
  [a-map]
  (assoc a-map :key2 "value2"))

(defn foo3
  [a-map]
  (assoc a-map :key3 "value3"))

(defn -main
  []
  (let [a-map {}]
    (do (foo1 a-map)
        (foo2 a-map)
        (foo3 a-map)
        a-map)))

显然这段代码是错误的,因为 a-map 没有在子例程范围之外更新。之所以这样写,只是因为与我当前的“正确”实现相比,它更清晰。预期结果是:

{:key1 "value1" :key2 "value2" :key3 "value3"}

我的问题是,以 clojure 方式完成任务的最佳方式是什么。

我考虑过嵌套几个 let 表达式,其中每个 let 可以保存更新后的 a-map 的结果。我还考虑使用 loop-recur 结构,其中 a-map 作为绑定传递。但是这两种方法看起来都不整洁。

任何建议将不胜感激。

干杯

编辑:为问题添加约束。函数foo1, foo2, foo3 实际上比a-map 需要更多的参数。而其中一些参数只能通过处理传递给-main的参数来确定。

【问题讨论】:

    标签: clojure functional-programming


    【解决方案1】:

    assoc 返回更新后的映射,因此您可以使用 -> 线程宏链接您的调用:

    (let [a-map (-> {} 
                    foo1
                    foo2
                    foo3)] ...)
    

    或者你可以使用comp:

    (let [a-map ((comp foo3 foo2 foo1) {})]...)
    

    【讨论】:

    • 啊,你说的很对,但实际上我的函数需要更多的参数,这些参数在链式调用的开始甚至无法确定。我正在编辑原始帖子以添加约束。还有什么想法吗?
    • 我的错。只要后续函数调用不需要破坏先前调用的结果,这没有任何区别。谢谢!
    • 使用线程宏版本我认为您不需要每个函数周围的括号。所以:(let [a-map (-> {} foo1 foo2 foo3)] ...)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-04-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-09
    • 1970-01-01
    相关资源
    最近更新 更多