OK, we're all familiar with double colon operator in R. Whenever I'm about to write some function, I use require(<pkgname>)
, but I was always thinking about using ::
instead. Using require
in custom functions is better practice than library
, since require
returns warning and FALSE
, unlike library
, which returns error if you provide a name of non-existent package.
On the other hand, ::
operator gets the variable from the package, while require
loads whole package (at least I hope so), so speed differences came first to my mind. ::
must be faster than require
.
And I did some analysis in order to check that - I've written two simple functions that load read.systat
function from foreign
package, with require
and ::
respectively, hence import Iris.syd
dataset that ships with foreign
package, replicated functions 1000 times each (which was shamelessly arbitrary), and... crunched some numbers.
Strangely (or not) I found significant differences in terms of user CPU and elapsed time, while there were no significant differences in terms of system CPU. And yet more strange conclusion: ::
is actually slower! Documentation for ::
is very blunt, and just by looking at sources it's obvious that ::
should perform better!
require
#!/usr/local/bin/r
## with require
fn1 <- function() {
require(foreign)
read.systat("Iris.syd", to.data.frame=TRUE)
}
## times
n <- 1e3
sink("require.txt")
print(t(replicate(n, system.time(fn1()))))
sink()
double colon
#!/usr/local/bin/r
## with ::
fn2 <- function() {
foreign::read.systat("Iris.syd", to.data.frame=TRUE)
}
## times
n <- 1e3
sink("double_colon.txt")
print(t(replicate(n, system.time(fn2()))))
sink()
Grab CSV data here. Some stats:
user CPU: W = 475366 p-value = 0.04738 MRr = 975.866 MRc = 1025.134
system CPU: W = 503312.5 p-value = 0.7305 MRr = 1003.8125 MRc = 997.1875
elapsed time: W = 403299.5 p-value < 2.2e-16 MRr = 903.7995 MRc = 1097.2005
MRr is mean rank for require
, MRc ibid for ::
. I must have done something wrong here. It just doesn't make any sense... Execution time for ::
seems way faster!!! I may have screwed something up, you shouldn't discard that option...
OK... I've wasted my time in order to see that there is some difference, and I carried out completely useless analysis, so, back to the question:
"Why should one prefer require
over ::
when writing a function?"
=)