For an R package I am working on (which creates an S4 class), I would like to delay loading some data until the user actually asks for it (because it may or not be required and loading it takes a little while). This would require me to set a slot's value within its getter (aka accessor) method if it has not previously been loaded. But I cannot get the new value to "stick". Here is an MRE:
setClass("A", representation(value = "numeric"))
setGeneric("value<-", function(x, value) standardGeneric("value<-"))
setGeneric("value", function(x) standardGeneric("value"))
setMethod("value<-", signature("A", "numeric"),
function(x, value)
{
x@value = value
x
})
setMethod("value", signature(x = "A"),
function(x)
{
if(!length(x@value))
value(x) <- 20
x@value
})
This produces the following result:
> a <- new("A")
> value(a)
[1] 20
> a
An object of class "A"
Slot "value":
numeric(0)
So the value() function returns the desired new value (20), but this value is not actually updated in the object. Doing x@value <- value
instead of value(x) <- 20
in the getter did not succeed either.
It seems the problem is that I am not returning the updated object in my getter (the way my setter does), but I have something else to return in my getter (the value).
What is the Right Way To Do This™?
Thank you!
EDIT:
After futher study of S4 pass-by-value semantics, I have come to the conclusion that this is Simply Not Possible™. If a slot is updated, the object must be returned, and you can't return something else instead. Can someone confirm my conclusion is correct?