7

RIで新しい参照クラスを実験しているときに、メソッドに「[[]]」表記を使用すると(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」関数を作成したいためです。したがって、メソッドを文字列として指定する必要があります。誰かが私がこれを達成する方法について何かアイデアがありますか?

4

3 に答える 3

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
于 2011-04-30T18:03:05.047 に答える
2

基本的に、R5 ref クラスは必要になるまでメソッドをキャッシュしません。これはおそらく一種の遅延評価です。

を介してメソッドにアクセスすると、キャッシングが行われます$。したがって、私の知る限り、[[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

たぶんもっと簡単な方法があります。

于 2011-04-30T12:22:33.657 に答える
0

John Chambers が修正できるように、r-devel でバグとして報告してください。

于 2011-04-30T13:04:43.813 に答える