R:环境的缓存/备忘录

Sim*_*Sim 5 oop caching r memoization proto

我想使用memoization来缓存某些昂贵操作的结果,这样就不会一遍又一遍地计算它们.

无论memoiseR.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())
Run Code Online (Sandbox Code Playgroud)

根据答案更新

根据是使用持久缓存还是非持久缓存,此问题可以有不同的答案.非持久性缓存(例如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
Run Code Online (Sandbox Code Playgroud)

我认为我遇到问题的原因R.cache是我将一个proto方法作为函数传递给了memoizedCall.proto方法R.cache以很难的方式绑定到环境中.在这种情况下,您需要做的是取消绑定函数(从实例化方法获取到简单函数),然后手动传递对象作为第一个参数.下面的示例演示如何工作(包括ReportReport$loaderproto对象:

# This will not memoize the call
memoizedCall(Report$loader$download_report)

# This works as intended
memoizedCall(with(Report$loader, download_report), Report$loader)
Run Code Online (Sandbox Code Playgroud)

我很想知道为什么R.cache使用普通函数绑定到环境但是使用proto实例化方法失败.

Vin*_*ynd 5

在您的代码中,每次调用该函数时都会重新记忆该函数。以下应该工作:它只被记忆一次,当它被定义时。

ProtoTester <- proto(
  calc = {
    fn <- function() print(runif(1))
    mfn <- memoise(fn)
    function(.) mfn()
  }
)
replicate(5, ProtoTester$calc())
Run Code Online (Sandbox Code Playgroud)