メモ化を使用して、特定の高価な操作の結果をキャッシュし、何度も計算されないようにしたいと考えています。
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
は で 1 回だけ呼び出されR.cache
ます。で 2 回呼び出され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