如何使用跟踪将 S4 泛型函数单步执行到实际调度的方法中?

How to use trace to step through S4 generic function into method actually dispatched?

我有一组简单的 S4 classes,只有一个通用方法。我希望能够使用 trace() 来调试 S4 方法。

$ cat s4class.R
add<-function(a,b){
    d=0 
    e=9 
    return(a+b)
}  
setClass('astrophys_object',
        representation(mass="numeric", spin="numeric", radius="numeric", 
                       v="numeric", x="numeric", charge="numeric"), 
        prototype(mass=1, spin=1.92e41, radius=6.957e8, v=c(0,0,0),
                  x=c(0,0,0), charge=0)
)
setClass('star',
        contains="astrophys_object",
        representation(type="character", metallicity="numeric", temp="numeric"),
        prototype(type="MS", metallicity=0.0122, temp=5700)
)
setClass('galaxy',
        contains="astrophys_object",
        representation(type="character", sfr="numeric"),
        prototype(type="spiral", sfr=1.65, mass=5.8e11, spin=1.0e67)
)
setGeneric("spin_object", function(object){
    standardGeneric("spin_object")
})
setMethod("spin_object", signature(object = "galaxy"), function(object){
    object@spin = 66
    return(object)
})
setMethod("spin_object", signature(object = "star"), function(object){
    object@spin = 99
    return(object)
})

我能够单步执行测试函数 add()

> trace(add, browser, at=1)
[1] "add"
> add(9,8)
Tracing add(9, 8) step 1 
Called from: eval(expr, p)
Browse[1]> n
debug: `{`
Browse[2]> n
debug at R/Whosebug.R#19: d = 0
Browse[2]> n
debug at R/Whosebug.R#20: e = 9
Browse[2]> n
debug at R/Whosebug.R#21: return(a + b)
Browse[2]> n
[1] 17

现在让我们尝试单步执行 spin_object 泛型方法。

> trace(spin_object, browser, at=1)
Constructing traceable class “nonstandardGenericFunctionWithTrace”
Environment of class “nonstandardGenericFunction” is locked; using global environment for new class
[1] "spin_object"
attr(,"package")
[1] ".GlobalEnv"
> s<-new('star')
> spin_object(s)
Tracing spin_object(s) step 1 
Called from: eval(expr, p)
Browse[1]> n
debug: `{`
Browse[2]> n
debug at R/Whosebug.R#45: standardGeneric("spin_object")
Browse[2]> s
debugging in: loadMethod(function (object) 
{
    object@spin = 99
    return(object)
}, "spin_object", <environment>)
debug: standardGeneric("loadMethod")
Browse[3]> n   ##### <<<---- If I step here, I end up stepping into "loadMethod" NOT spin_object
exiting from: loadMethod(function (object) 
{
    object@spin = 99
    return(object)
}, "spin_object", <environment>)
An object of class "star"
Slot "type":
[1] "MS"

Slot "metallicity":
[1] 0.0122

Slot "temp":
[1] 5700

Slot "mass":
[1] 1

Slot "spin":
[1] 99

Slot "radius":
[1] 695700000

Slot "v":
[1] 0 0 0

Slot "x":
[1] 0 0 0

Slot "charge":
[1] 0

问题 我如何实际逐步完成为 star class 分派的 spin_object?如果我尝试进入 Browser[3],我最终会进入 loadMethod 并且 NOT 正在调度的方法。

为此,我需要为 trace()

指定签名参数
trace(what='spin_object', tracer=browser, at=1, signature='star')