R:从 S4 方法中更改 S4 对象
R: Changing an S4 object from within an S4 method
我有一个 S4 对象,表示包含一些数据和相同 class 的其他对象的递归树结构。我还有一个递归函数来修改树中每个节点中的两个槽。当我这样做时,该函数(称之为 "propagate()")会正确地完成它的工作:
> obj <- treeObj(4, 5)
> slotNames(obj)
[1] "x" "y" "listOfOtherTreeObjs"
> obj <- propagate(obj, 1, 4)
我可以编写一个像这样的函数,它接受一个参数并用该数据填充树,没问题。
不过,我想要的是能够从根对象的方法中调用 propagate():
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)
})
在此方法中,propagate() 似乎正常运行,但其结果似乎并未以在 transform() 方法定义中可检测到的方式分配给父对象。我的问题:
我想这与 R 的按值调用性质有关,我无法影响用于调用转换函数的对象的值。这是正确的还是我只是愚蠢而这应该有效?
有什么 R 魔法可以解决这个问题吗?调用 'assign()' 函数以强制对象的新定义替换当前对象的某种方式?或者什么?
是否有更 R-ish 的方法来构建我的递归对象来支持这种事情?
提前致谢。
要完成这项工作,您需要做两件事:
1) 据推测,递归不会永远持续下去,即在某个时候,一个对象不会包含到另一个对象的 link,因为它位于树的底部。因此,您需要其他树对象列表为 NULL 的可能性。您可以使用 class 联合来执行此操作:
setClassUnion("listOfOtherTreeObjsOrNULL",c("listOfOtherTreeObjs","NULL"))
然后在对象的第三个插槽中使用的正确 class 是这个新的 class 并集。
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
从您的函数中获取任何内容,因此您只是修改了未保存在任何地方的对象的副本。
我有一个 S4 对象,表示包含一些数据和相同 class 的其他对象的递归树结构。我还有一个递归函数来修改树中每个节点中的两个槽。当我这样做时,该函数(称之为 "propagate()")会正确地完成它的工作:
> obj <- treeObj(4, 5)
> slotNames(obj)
[1] "x" "y" "listOfOtherTreeObjs"
> obj <- propagate(obj, 1, 4)
我可以编写一个像这样的函数,它接受一个参数并用该数据填充树,没问题。
不过,我想要的是能够从根对象的方法中调用 propagate():
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)
})
在此方法中,propagate() 似乎正常运行,但其结果似乎并未以在 transform() 方法定义中可检测到的方式分配给父对象。我的问题:
我想这与 R 的按值调用性质有关,我无法影响用于调用转换函数的对象的值。这是正确的还是我只是愚蠢而这应该有效?
有什么 R 魔法可以解决这个问题吗?调用 'assign()' 函数以强制对象的新定义替换当前对象的某种方式?或者什么?
是否有更 R-ish 的方法来构建我的递归对象来支持这种事情?
提前致谢。
要完成这项工作,您需要做两件事:
1) 据推测,递归不会永远持续下去,即在某个时候,一个对象不会包含到另一个对象的 link,因为它位于树的底部。因此,您需要其他树对象列表为 NULL 的可能性。您可以使用 class 联合来执行此操作:
setClassUnion("listOfOtherTreeObjsOrNULL",c("listOfOtherTreeObjs","NULL"))
然后在对象的第三个插槽中使用的正确 class 是这个新的 class 并集。
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
从您的函数中获取任何内容,因此您只是修改了未保存在任何地方的对象的副本。