Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add extra arguments to implicit S4 generic for a primitive function

Take the function names: that's a primitve function in R. For primitive functions, an implicit S4 generic is created, so it is possible to construct S4 methods for that function.

Take an S4 class defined as follows :

setClass("aClass",
         representation=list(
           values = "character",
           id = "numeric"
           ),
         prototype=list(
           values = character(0),
           id = numeric(0)),
         validity=function(object){
           length(object@values)==length(object@id)
         }
        )

Now I want to create a function to extract the names, either sorted or unsorted. I wanted to do this using the function names to avoid having to make a new function getNames() or whatever, as that's less intuitive.

The following gives an idea of what needs to be done:

setMethod("names",signature="aClass",
   function(x,ordered=TRUE){
      if(ordered)
        x@values[x@id]
      else
        x@values
   }

This won't work, as names is a primitive function and ordered is not an argument for the implicit generic.

How can I make this work under the following conditions:

  • the names function should keep its original behaviour for all other objects, including objects from other packages.
  • the code should be acceptable for use in a package
  • the code should be acceptable by the high standards set by eg Bioconductor.
like image 448
Joris Meys Avatar asked Aug 26 '13 13:08

Joris Meys


1 Answers

The generic is available as

> getGeneric("names")
standardGeneric for "names" defined from package "base"

function (x) 
standardGeneric("names", .Primitive("names"))
<environment: 0x459c9c0>
Methods may be defined for arguments: x
Use  showMethods("names")  for currently available ones.

so from the signature you can see that the short answer is that you can't add arguments. You'd definitely not want to create your own function names. A hack would use a package-global variable getOption("pkg_names_ordered") but I wouldn't partake of that solution myself.

In some ways the contract set out by names does not say anything about order (for instance, names and numerical indecies are often used to subset; are the numerical indices for the ordered names, or the unordered names?), so you're really proposing a new generic anyway.

like image 191
Martin Morgan Avatar answered Nov 03 '22 00:11

Martin Morgan