Использование нотации «[[]]» для справочных методов класса
-
27-10-2019 - |
Вопрос
При экспериментировании с новыми эталонными классами в RI заметили какое -то странное поведение, если вы используете нотацию «[]]» для методов (x [["dosomething"]] вместо x $ dosomething). Эта нотация работает для полей, но я изначально думал, что это не сработает для методов, пока я не обнаружил, что если вы выполните «класс (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», которая применяет указанный метод на каждом из объектов внутри. Поэтому мне нужно указать метод как строку. У кого -нибудь есть идеи, как я могу этого добиться?
Решение
Вот класс
.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
Другие советы
В основном класс R5 Ref не кэширует метод, пока он не будет необходим. Это, вероятно, своего рода отсроченная оценка.
И кэширование происходит при доступе к методу через $
Анкет Итак, 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
Может быть, есть более простой способ.
Сообщите как ошибку на R-Devel, чтобы Джон Чемберс мог это исправить.