我有一个S4对象,该对象表示包含某些数据和同一类的其他对象的递归树结构。我还有一个递归功能,可以修改树中每个节点的两个插槽。在执行此操作时,该函数(称为“ propagate()”)会正确执行其操作:
> obj <- treeObj(4, 5)
> slotNames(obj)
[1] "x" "y" "listOfOtherTreeObjs"
> obj <- propagate(obj, 1, 4)
我可以编写一个这样的函数,该函数接受一个参数,并使用该数据填充树,没问题。
不过,我想要的是能够从根对象的方法内调用property():
setMethod("transform", signature="treeObj",
definition=function(object, i, j) {
object@x <- i; object@y <- j;
object <- propagate(object, i, j);
... (do some other stuff in the tree)
})
在此方法中,property()似乎可以正常运行,但是其结果似乎并没有以transform()方法定义中可检测的方式分配给父对象。我的问题:
我想这与R的按值调用性质有关,并且我不能影响用于调用转换函数的对象的值。那是正确的还是我只是愚蠢,这应该起作用?
是否有R魔术可以解决此问题?以某种方式调用“ assign()”函数来强制对象的新定义替换当前对象?还是什么?
是否有更多的R-ish方法来构建我的递归对象以支持这种事情?
谢谢。
答案 0 :(得分:1)
要完成此工作,需要做两件事:
1)推测,递归不会永远持续下去,即某个对象在某个时刻将不包含到另一个对象的链接,因为它位于树的底部。因此,您需要其他树objs的列表为NULL的可能性。您可以通过类联合来做到这一点:
setClassUnion("listOfOtherTreeObjsOrNULL",c("listOfOtherTreeObjs","NULL"))
然后在对象的第三个插槽中使用的正确类是这个新的类联合。
2)在为transform
定义方法时,它需要看起来像这样:
function(object,i,j){
## do whatever you want with i and j
if(is.null(object@listOfOtherTreeObjs)) return(object)
else{
object@listOfOTherTreeObjs <- lapply(object@listOfOtherTreeObjs,propagate)
return(object)
}
}
您的更改似乎没有生效的原因是,您没有return
从函数中进行任何操作,因此您只修改了未保存在任何地方的对象的副本。