我想使用 memoization来缓存某些昂贵操作的结果,这样就不会一遍又一遍地计算它们. memoise和R.cache都符合我的需求.但是,我发现调用之间的缓存并不健壮. 这是一个演示我看到的问题的例子
memoise和R.cache都符合我的需求.但是,我发现调用之间的缓存并不健壮.
这是一个演示我看到的问题的例子:
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调用一次.它将通过备忘录被调用两次.
> 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实例化方法失败了.
在您的代码中,每次调用函数时都会重新记忆该函数.以下内容应该有效:只有在定义时才会记忆一次.
ProtoTester <- proto( calc = { fn <- function() print(runif(1)) mfn <- memoise(fn) function(.) mfn() } ) replicate(5, ProtoTester$calc())