【发布时间】:2016-02-24 15:31:44
【问题描述】:
在无状态 Clojure 库的开发中,我遇到了一个问题:许多函数必须使用相同的参数重复调用。由于到目前为止一切都是无副作用的,这将始终导致相同的结果。我正在考虑如何让它更具表现力。
我的库是这样工作的:每次调用一个函数时,它都需要传递一个状态哈希映射,该函数返回一个带有操作状态对象的替换。因此,这使所有内容都保持不变,并且每种状态都保留在库之外。
(require '[mylib.core :as l])
(def state1 (l/init-state))
(def state2 (l/proceed state1))
(def state3 (l/proceed state2))
如果继续不应该重复执行相同的操作,我有几个选项来解决这个问题:
选项 1:“手工操作”
将必要的状态存储在 state-hash-map 中,并仅在必要时更新。意味着:拥有一个复杂的机制,知道哪些部分必须重新计算,哪些不需要。这总是可能的,就我而言,这不是那么微不足道。如果我实现了这个,我会产生更多的代码,最终更容易出错。那么有必要吗?
选项 2:记忆
所以在库中的关键点使用memoize 函数很容易: 在这些点上,我预计可能会重复使用相同的参数调用函数。这是另一种编程哲学:对每个步骤进行建模,就好像它是第一次运行一样。并将多次调用的事实分离到另一个实现。 (这让我想起了react/om/reagent的render函数的想法)
选项 3:core.memoize
但是记忆是有状态的——当然。这 - 例如 - 当 lib 在网络服务器中运行时成为一个问题。服务器将继续用捕获的结果填充内存。然而,就我而言,只捕获每个用户会话的计算结果是有意义的。因此,将缓存附加到前面描述的 state-hash-map 是完美的,它将由 lib 传回。
看起来 core.memoize 为这项工作提供了一些工具。不幸的是,它没有很好的记录 - 我真的找不到与所描述情况相关的有用信息。
我的问题是:我是否或多或少正确估计了可能的选项?或者还有其他我没有考虑过的选择吗?如果没有,看起来 core.memoize 是要走的路。然后,如果有人可以在手边给我一个简短的模式,我将不胜感激,应该在这里使用。
【问题讨论】:
标签: clojure functional-programming clojurescript