3

When I type the function name of a generic in to my console, I expect to see a call to UseMethod. For example, the documentation for determinant calls it a generic and I get the following output when I type it in to my console:

> determinant
function (x, logarithm = TRUE, ...) 
UseMethod("determinant")
<bytecode: 0x55fb617086b8>
<environment: namespace:base> #

The documentation for rep makes a similar claim, but my console does not give similar output:

> rep
function (x, ...)  .Primitive("rep")

And my attempts to extend rep have been unsuccessful.

This leaves me with two possibilities. Either I have a very bad understanding of R's generic functions or rep is not a generic at all. Which is it?

J. Mini
  • 1,868
  • 1
  • 9
  • 38

1 Answers1

2

In the code for the interal rep function it calls

DispatchOrEval(call, op, "rep", args, rho, &a, 0, 0)

which will only do generic dispatching if your function is "an object" which can be seen here.

Matrices in R aren't considered "objects", they are primitive types so no dispatching will take place.

is.object(matrix(1:3))
# [1] FALSE

This is a code optimization for functions that are called frequently and need to be fast.

So you will not be able to create a custom rep function for matrices using S3 generics. you'd have to shadow the base function if you want to change the behavior (which might break functions that rely on the existing behavior). Probably even better to write your own function with a different name to do what you want.

MrFlick
  • 195,160
  • 17
  • 277
  • 295
  • Is there anywhere other than the source code that details this type of behavior? The impression that I've got from this madness is that one needs to read R's source code to discover what the documentation meant when it knowingly mislead you. I'd like to be able to give R a great deal more faith than that. Surely, this is documented somewhere? Is there even a name for these unextensible generics? – J. Mini Feb 22 '21 at 01:13
  • 1
    The [Internal Generic Functions documentation](https://stat.ethz.ch/R-manual/R-patched/library/base/html/InternalMethods.html) lists `rep` and has a line saying "_For efficiency, internal dispatch only occurs on objects, that is those for which is.object returns true._". I have no idea how "internal dispatch" differs from the dispatch that we want here, but it seems relevant. – J. Mini Feb 23 '21 at 17:24