7

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.
Joris Meys
  • 106,551
  • 31
  • 221
  • 263

1 Answers1

9

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.

Martin Morgan
  • 45,935
  • 7
  • 84
  • 112
  • Thanks for the answer, but that's what I said in my question: I can't use an extra argument. The numerical indices are for the ordered names and a set of other slots (actual object is a lot more complex and not all slots can be ordered). I use an extra slot to indicate whether the object has been ordered or not. I have a long way around to "unorder" the ordered names. But I hoped to find a way to do this without hacking around. A package-global variable is the kind of hack that I wouldn't even consider a valid option. :) – Joris Meys Aug 26 '13 at 14:32
  • 2
    Yes from your question it seemed like you knew the answer was no, but since you asked the question, I answered ;) – Martin Morgan Aug 26 '13 at 15:41
  • I hoped there was some way around I wasn't aware of, but I'm afraid I'll have to settle with a "no" :) I give it a few more days, and then you have your accepted answer. – Joris Meys Aug 29 '13 at 09:13
  • 1
    I believe those few days are passed now... :) – Michele May 16 '14 at 23:08
  • they are very passed – Zafar Mar 15 '20 at 23:10