Reputation: 539
I'm trying to implement object-specific method caching in R. I have many different kinds of objects, and many of them implement functions that get called often, take a long time to run, and whose inputs/outputs don't change between executions. So to save time, I want to cache the outputs of these methods to a hash-map, which maps the hash of the parameter inputs to the output. The catch is that these long-running methods reference the object fields, which means that I need the caching to be object-specific. I can't implement a global caching process, because executing the same function on two different instances of the same object typically produces different outputs.
To do this, I've implemented a parent class Cache
, which has a hash-map, and implements the 'cache' function. This object can then be inherited by other objects to easily implement object-specific method-caching.
In order to streamline the process, I've also implemented a decorator, so that the methods of the child objects can be easily wrapped in the caching function.
Here's my code:
# Define the infix decorator function
`%decorate%` = function(decorator, f) {
decorator(f)
}
# Cache parent class
Cache =
# ----
setRefClass(
'Cache',
fields =
c(
# PRIVATE: hash map of inputs to outputs
"prev_output_hash_map__"
),
methods =
list(
# Initialize the private values.
initialize =
function(...) {
callSuper(
prev_output_hash_map__ = r2r::hashmap(),
...
)
},
cache =
function(f) {
function(refresh = F,...) {
# Hash the function name and it's inputs
input_hash__ =
rlang::hash(
list(
deparse1(f), # The code of the function
... # The parameter inputs to the function
)
)
# Check to see if the input hash is present in the hash map
# If it isn't execute the inner function and save the results
if(is.null(prev_output_hash_map__[input_hash__][[1]]) | refresh) {
prev_output_hash_map__[[input_hash__]] <<- f(...)
}
# Return the previously saved output
return(prev_output_hash_map__[input_hash__][[1]])
}
}
)
)
# Child class which will implement caching on one or more of its methods
CachingObject =
setRefClass(
"CachingObject",
contains = "Cache",
methods =
list(
# A long-running method that I want to cache the output of
long_running_function =
cache %decorate% function(input1, input2) {
Sys.sleep(10)
return(input1 + input2)
}
)
)
I've verified that the caching logic works correctly outside of the reference class. The problem here is that the 'cache' function is a method of the Cache object, and not defined in the global environment. This means that the method isn't visible when the child object CachingObject
is being defined, and I get the following error:
Error in cache %decorate% function(input1, input2) { :
object 'cache' not found
Is there some way to reference the methods of a parent object in the midst of the definition of a child object? If not, is there a way to accomplish what I'm trying to do here?
Upvotes: 1
Views: 48