我想使用延迟赋值为S4对象的插槽分配新值。 这个赋值基本上是一个数据库查询,我只希望在实际使用该值时执行数据库查询。
但是为了测试,这也可以:
testFunction <- function(id = 1){
print("running query")
return(id)
}
delayedAssign("test", testFunction(id = 2))
这很有效。 &#34;运行查询&#34;仅在调用测试时打印,而不是在分配时打印。与之相反:
test2 <- testFunction(id = 2)
现在我希望能够做同样的事情,但后来就是一个插槽。
delayedAssign("someObject@slotName", testFunction(id = 2))
遗憾的是,这会创建一个对象名称“someObject @ slotName&#39;在当前的环境中。 关于如何解决这个问题的任何想法?
答案 0 :(得分:3)
这代表了一些黑客攻击,具有令人不快的实现细节。这是一个S4类,环境为插槽
.B <- setClass("B", representation(b="environment"))
我注意初始化,所以每个实例都有自己的环境(而不是所有实例共享相同的环境,如果有单例,这将是默认和适当的)
setMethod(initialize, "B",
function(.Object, ..., b=new.env(parent=emptyenv()))
{
b[["value"]] <- NA
callNextMethod(.Object, ..., b=b)
})
让我们定义泛型来设置和检索延迟分配值
setGeneric("delay<-", function(x, ..., value) standardGeneric("delay<-"))
setGeneric("delay", function(x, ...) standardGeneric("delay"))
然后实现方法,在我们的环境中为元素“值”指定值
setReplaceMethod("delay", "B", function(x, ..., value) {
force(value) # don't want to be _too_ lazy
delayedAssign("value", testFunction(value), assign.env=x@b)
x
})
并检索它
setMethod("delay", "B", function(x, ...) x@b[["value"]])
这是我们劳动的产物......
> b <- .B()
> delay(b)
[1] NA
> delay(b) <- 1 # no type safety; could use, e.g., delay<-,numeric-method
> delay(b)
[1] "running query"
[1] 1
带有一些奇怪的引用语义(因为b1和b共享相同的环境)会让我们的用户感到惊讶(甚至可能是我们的用户期望引用语义)
> b1 <- b # reference semantics, delayed
> delay(b1) <- 2
> delay(b)
[1] "running query"
[1] 2