R match.call () for S4 methods

I am currently writing a method for an S4 class and I would like to get the method call as if it were a function and using match.call ().

Here is my minimal example of what I am doing:

setClass(
  Class = "AClass",
  representation = representation(
    name = "character"
  )
)

setGeneric("meth1", function(object, ...) {
  standardGeneric("meth1")
})

setMethod(
  f = "meth1",
  signature = "AClass",
  definition = function(object, method, ..., warnings = TRUE) {
    # ...
    print(match.call())

    return(NA)
})

      

With this definition, I see:

> meth1(new("AClass"), method = "MClust")
.local(object = object, method = "MClust")
[1] NA
> meth1(new("AClass"), method = Mclust)
.local(object = object, method = ..1)
[1] NA

      

Questions:

  • Why, when assigning a function to an argument 'method', the content obtained from match.call()

    for that argument is ..1

    insetad fo "Mclust"

    ?

  • Why is the function name from match.call()

    there .local

    instead meth1

    ?

  • How can I get "Mclust"

    from a variable method

    in a function?

+3


source to share


1 answer


There are some problems with how it match.call

works when there are ...

multiple levels of function calls. This has to do with match.call

searching through the lexical stack to find ...

instead of dynamic stack instead. I wrote a package to fix these problems:

devtools::install_github("brodieg/matchcall")  # <-- the package in question
library(matchcall)
setMethod(
  f = "meth1",
  signature = "AClass",
  definition = function(object, method, ..., warnings = TRUE) {
    # ...
    print(match.call())
    print(match_call())
    print(match_call(2))
    return(NA)
  })
meth1(new("AClass"), method = Mclust)

      

Outputs:

.local(object = object, method = ..1)               # match.call
.local(object = object, method = Mclust)            # match_call(), my package
meth1(object = new("AClass"), method = Mclust)      # match_call(2), my package offset
[1] NA

      

So, to answer question 2, the reason you are getting .local

is that there is a sequence of calls that ultimately lead to the evaluation of the function you defined, and that S4 stores that function as .local

.

The answer to question 1 is tricky, but you can see the details in the vignette included in my package. Note that there are names inside the C code arguments , etc. ( from R Internals ) : ...

..1

..2



Recall that the evaluation frame for a function initially contains the name = value pairs from the matched call, and therefore the same is true for .... The value ... is a (special) pair list, whose elements are denoted by special characters ... 1, ..2, ... which have the DDVAL bit: when one of them is encountered, it is scanned (via ddfindVar) in the character value ... in the evaluation frame.

To question 3, I don't understand this. Do you want to be able to enter an unspecified variable as an argument to "method" and then interpret it as a character?

Please note that the package currently only runs on github, but you can use sys.calls

to suit your needs. For example, if we run print(sys.calls())

inside your method, we get:

[[1]]
meth1(new("AClass"), method = Mclust)

[[2]]
meth1(new("AClass"), method = Mclust)

[[3]]
.local(object, ...)

      

You can work with this directly, but it will only work if you specify the names of the arguments in full in the call (i.e. if someone does meth1(x, "blah")

, you won't get part of it method=

in sys.calls

If you have multiple arguments or partially specified arguments ( for example meth=X

), you will need to do more work to match the material (and what exactly does it match_call

).

+2


source







All Articles