9

Is it possible in R to protect function names (or variables in general) so that they cannot be masked.

I recently spotted that this can be a problem when creating a data frame with the name "new", which masked a function used by lmer and thus stopped it working. (Recovery is easy once you know what the problem is, here "rm(new)" did it.)

Andi F
  • 191
  • 5

4 Answers4

9

There is an easy workaround for your problem, without worrying about protecting variable names (though playing with lockBinding does look fun). If a function becomes masked, as in your example, it is still possible to call the masked version, with the help of the :: operator.

In general, the syntax is packagename::variablename.

(If the function you want has not been exported from the package, then you need three colons instead, :::. This shouldn't apply in this case however.)

Richie Cotton
  • 118,240
  • 47
  • 247
  • 360
  • Doesn't work if I'm calling a function, in a package, which relies on a function elsewhere which inadvertently has become masked. – Andi F Aug 11 '10 at 14:56
  • @AndyF yeah that's a good point. I'm seeing a theme in the answers: R does not protect users from themselves. This is very Linux-like. ;) – JD Long Aug 12 '10 at 14:29
4

Maybe use environments! This is a great way to separate namespaces. For example:

> a <- new.env()
> assign('printer', function(x) print(x), envir=a)
> get('printer', envir=a)('test!')
[1] "test!"
Vince
  • 7,608
  • 3
  • 41
  • 46
2

@hdallazuanna recommends (via Twitter)

new <- 1
lockBinding('new', globalenv())

this makes sense when the variable is user created but does not, of course, prevent overwriting a function from a package.

JD Long
  • 59,675
  • 58
  • 202
  • 294
0

I had the reverse problem from the OP, and I wanted to prevent my custom functions in .Rprofile from being overridden when I defined a variable with the same name as a function, but I ended up putting my functions to ~/.R.R and I added these lines to .Rprofile:

if("myfuns"%in%search())detach("myfuns")
source("~/.R.R",attach(NULL,name="myfuns"))

From the help page of attach:

One useful ‘trick’ is to use ‘what = NULL’ (or equivalently a
length-zero list) to create a new environment on the search path
into which objects can be assigned by assign or load or
sys.source.

...

## create an environment on the search path and populate it
sys.source("myfuns.R", envir = attach(NULL, name = "myfuns"))
nisetama
  • 7,764
  • 1
  • 34
  • 21