1. Method Lookup for Primitive Generics
For many data analyses, the most time-consuming tasks are
2. Writing code
writing, debugging and maintaining the code. This means that R is optimized to make these tasks as quick as possible. In some cases however, the speed that the code runs is more important. Functions for whom speed is a critical factor often aren't actually written in R. Instead, they are written in C.
3. R vs. C
The reason for this is that C code typically runs faster than R code, so writing in C increases the performance. The tradeoff is that C code usually takes longer to write, and is harder to debug.
4. R -> C
R has several interfaces to the C language, and the highest performance of these is known as the
5. R -> C
"primitive" interface. This is reserved for a few fundamental features in base-R.
Functions that use the primitive interface are called, as you might expect, "primitive functions". Examples of primitive functions include
6. exp
common mathematical functions like exp and sin, arithmetic operators like plus and minus, and language constructs like if and for.
Primitive functions can also be generic, and it is important to be aware that these behave slightly differently than other generic functions.
Before we get to that, you might wonder which functions we are talking about.
7. S3PrimitiveGenerics
You can see a complete list of primitive generics using dot-S3PrimitiveGenerics. There are nearly 30 functions in total. That isn't many, but several of these are functions that you might use on a regular basis. The big difference between a primitive generic and a regular generic is what happens when a suitable method can't be found.
8. all_of_time
For example, consider this string representing the start of time according to POSIX, and the end of time according to Mayan prophecy. You can convert it to an actual date variable using as-dot-Date.
Now look at what happens if the class is overridden. as-dot-Date isn't a primitive generic, so when you override the class to "date_strings", no method can be found, and an error is thrown.
By contrast, look at what happens with the length function. length is a primitive generic, and it's so important that you don't want it to break, just because the class has been changed. For primitive functions, rather than an error being thrown when no suitable method is found, those functions will just go directly to the C-code, using typeof to determine the type of the variable. In this case, the length is correctly calculated to be two.
9. Summary
In summary, some R functions are actually written in C, for performance reasons. Core functionality uses the primitive interface to C. There are a few S3 primitive generic functions, which can be listed using dot-S3PrimitiveGenereics. These functions have one important change in behavior regarding S3: if a suitable method is not found, regular S3 functions will throw an error. Primitive functions are different. If no suitable method is found, they will call the C-code, using typeof to determine the type of input.
10. Let's practice!