对引用类方法使用“[[]]”表示法

时间:2011-04-30 11:05:27

标签: r reference-class

在R中尝试新的引用类时,如果对方法使用“[[]]”符号(X [[“doSomething”]]而不是X $ doSomething),我会注意到一些奇怪的行为。这种表示法适用于字段,但我最初认为它不适用于方法,直到我发现如果你执行“class(X $ doSomething)”,然后你可以使用“[[]]”。下面的简单示例说明了这一点。

setRefClass("Number", 
  fields = list(
    value = "numeric"
  ),
  methods = list(
    addOne = function() {
      value <<- value + 1
    }
  )
)

X <- new("Number", value = 1)

X[['value']]         # 1

X[["addOne"]]()      # Error: attempt to apply non-function
class(X[["addOne"]]) # NULL

class(X$addOne)      # "refMethodDef"

# Now the following works!
X[["addOne"]]()      # sets X$value = 2
class(X[["addOne"]]) # "refMethodDef"

我遇到这个的原因是因为我想在列表中将我的对象组合在一起并创建一个“applyMethod”函数,该函数在其中的每个对象上应用指定的方法。因此,我需要将方法指定为字符串。有没有人有任何想法我怎么能做到这一点?

3 个答案:

答案 0 :(得分:4)

这是一个班级

.A <-
    setRefClass("A",
                fields=list(x="numeric"),
                methods=list(foo=function() x))

如果我有一个实例a并希望使用'$'构建对'foo'方法的调用,我可以

eval(substitute(a$FUN(), list(FUN="foo")))

因此,我将创建一个类Alist,其中包含类A的元素列表(可以通过编程方式强制执行),并且具有.delegate方法将对列表的所有元素应用任意方法。然后,我将添加一个委托foo

的方法
.delegate <- function(FUN, ...)
{
    lapply(elts, function(elt, ...) {
        eval(substitute(elt$FUN(...), list(FUN=FUN, ...)))
    })
}

.Alist <-
    setRefClass("Alist",
                fields=list(elts="list"),
                methods=list(
                  initialize = function(...) callSuper(elts=list(...)),
                  .delegate = .delegate,
                  foo=function() .delegate("foo")))

然后使用它

> aList <- .Alist$new(.A$new(x=1), .A$new(x=2))
> aList$foo()
[[1]]
[1] 1

[[2]]
[1] 2

答案 1 :(得分:2)

基本上R5 ref class在有必要之前不会缓存方法。这可能是一种延迟评估。

当您通过$访问该方法时,会发生缓存。 所以,AFAIK,无法通过[[string]]

访问该方法

但你可以使用.dollarForEnvRefClass找到一个解决方法:

> X <- new("Number", value = 1)
> ls(X@.xData)
[1] "value" # no methods named "addOne" before caching
> X[["addOne"]]
NULL
> methods:::.dollarForEnvRefClass(X, "addOne") # cache it
Class method definition for method addOne()
function () 
{
    value <<- value + 1
}
<environment: 0x116a4aa00>
> ls(X@.xData)
[1] "addOne" "value"  # you can find it
> X$value # value is 1
[1] 1
> X[["addOne"]]() # call the method
> X$value  # the method works
[1] 2

如果您对更多细节感兴趣,请参阅实施:
http://svn.r-project.org/R/trunk/src/library/methods/R/refClass.R

也许有更直截了当的方式。

答案 2 :(得分:0)

报告r-devel上的错误,以便John Chambers可以修复它。