【发布时间】:2015-02-20 16:55:26
【问题描述】:
在对序列的每个元素的函数应用程序之间实现映射函数以及可更新状态的最佳方式是什么?为了说明这个问题,让我们假设我们有以下问题:
我有一个数字向量。我想要一个新序列,其中每个元素乘以 2,然后在序列中添加 10 的数量,直到并包括当前元素。例如来自:
[20 30 40 10 20 10 30]
我要生成:
[40 60 80 21 41 22 62]
在不添加 10 的情况下,可以使用高级抽象来制定解决方案:
(map #(* 2 %) [20 30 40 10 20 10 30])
计数更新迫使我“进入基本”,我想出的解决方案是:
(defn my-update-state [x state]
(if (= x 10) (+ state 1) state)
)
(defn my-combine-with-state [x state]
(+ x state))
(defn map-and-update-state [vec fun state update-state combine-with-state]
(when-not (empty? vec)
(let [[f & other] vec
g (fun f)
new-state (update-state f state)]
(cons (combine-with-state g new-state) (map-and-update-state other fun new-state update-state combine-with-state))
)))
(map-and-update-state [20 30 40 50 10 20 10 30 ] #(* 2 %) 0 my-update-state my-combine-with-state )
我的问题:这是解决问题的适当/规范方法还是我忽略了一些重要的概念/功能。
PS:
原来的问题是遍历 AST(抽象语法树),生成新的 AST 和更新符号表,所以在提出上述问题的解决方案时请牢记。
我不担心炸毁堆栈,所以用循环+递归替换不是 我在这里担心。
使用全局 Vars 或 Refs 而不是将 state 作为参数传递是否是明确的禁忌?
【问题讨论】:
-
使用全局可变状态不是禁忌,但最好避免。特别是对于像这样你可以组合函数的事情。但是,Clojure 并不是纯粹的,所以如果有 refs 或 atom 可以通过各种方式改进您的代码,请使用它们。
标签: clojure