nI想使用memoization来缓存某些昂贵操作的结果,以免它们一遍又一遍地被重复计算。R:缓存/环境备份
memoise和3210符合我的需求。但是,我发现缓存在呼叫中不稳健。
下面是一个说明我看到了问题的一个例子:基于答案
library(memoise)
# Memoisation works: b() is called only once
a <- function(x) runif(1)
replicate(5, a())
b <- memoise(a)
replicate(5, b())
# Memoisation fails: mfn() is called every single time
ProtoTester <- proto(
calc = function(.) {
fn <- function() print(runif(1))
mfn <- memoise(fn)
invisible(mfn())
}
)
replicate(5, ProtoTester$calc())
更新
这个问题可以基于持久或非持久的缓存是否有不同的答案用过的。非永久性缓存(例如memoise
)可能需要单独分配,然后下面的答案是一个不错的方法。持久性缓存(例如R.cache
)适用于多个分配,应该是对于多个分配的健壮性。上述方法适用于R.cache
。尽管有多个作业,fn
只能用R.cache
调用一次。它将被调用memoise
两次。
> ProtoTester <- proto(
+ calc = function(.) {
+ fn <- function() print(runif(1))
+ invisible(memoizedCall(fn))
+ }
+)
> replicate(5, ProtoTester$calc())
[1] 0.977563
[1] 0.1279641
[1] 0.01358866
[1] 0.9993092
[1] 0.3114813
[1] 0.97756303 0.12796408 0.01358866 0.99930922 0.31148128
> ProtoTester <- proto(
+ calc = function(.) {
+ fn <- function() print(runif(1))
+ invisible(memoizedCall(fn))
+ }
+)
> replicate(5, ProtoTester$calc())
[1] 0.97756303 0.12796408 0.01358866 0.99930922 0.31148128
为什么我认为我有一个问题,R.cache
的原因是,我传递一个proto
方法的功能memoizedCall
。 proto
方法被绑定到环境的方式,R.cache
很难。在这种情况下你必须做的是取消绑定函数(从实例化的方法获得一个简单的函数),然后手动传递该对象作为第一个参数。下面的示例演示如何工作(包括Report
和Report$loader
是proto
对象:
# This will not memoize the call
memoizedCall(Report$loader$download_report)
# This works as intended
memoizedCall(with(Report$loader, download_report), Report$loader)
我很想知道为什么R.cache
作品绑定到环境中的正常功能,但无法与proto
实例化的方法
我误解了memoise实现使用的对象标识机制。因为'R.缓存'具有与记忆相关的持久性我认为它的设计基于功能的内容/代码而不是其内部的R ID,否则它不会跨会话工作。以memoization作为副作用创建表达式是一个很好的模式。你的代码甚至可以在任务分配(多次执行多次分配'fn'的ProtoTester分配)时使用'R.cache'工作。我想知道为什么它以前不适合我... – Sim 2012-07-06 16:18:39
我再次检查并发现'R.cache'与我的旧代码一起工作。我一定忽略了一件简单的事情。 – Sim 2012-07-06 16:20:58
我更新了问题并澄清了涉及持久性时的行为差异。 – Sim 2012-07-06 16:33:52