Yesterday I learned from Bill Venables how local() can help create static functions and variables, e.g.,
example <- local({
hidden.x <- "You can't see me!"
hidden.fn <- function(){
cat("\"hidden.fn()\"")
}
function(){
cat("You can see and call example()\n")
cat("but you can't see hidden.x\n")
cat("and you can't call ")
hidden.fn()
cat("\n")
}
})
which behaves as follows from the command prompt:
> ls()
[1] "example"
> example()
You can see and call example()
but you can't see hidden.x
and you can't call "hidden.fn()"
> hidden.x
Error: object 'hidden.x' not found
> hidden.fn()
Error: could not find function "hidden.fn"
I’ve seen this kind of thing discussed in Static Variables in R where a different approach was employed.
What the pros and cons of these two methods?
Encapsulation
The advantage of this style of programming is that the hidden objects won’t likely be overwritten by anything else so you can be more confident that they contain what you think. They won’t be used by mistake since they can’t readily be accessed. In the linked-to post in the question there is a global variable,
count, which could be accessed and overwritten from anywhere so if we are debugging code and looking atcountand see its changed we cannnot really be sure what part of the code has changed it. In contrast, in the example code of the question we have greater assurance that no other part of the code is involved.Note that we actually can access the hidden function although its not that easy:
Object Oriented Programming
Also note that this is very close to object oriented programming where
exampleandhidden.fnare methods andhidden.xis a property. We could do it like this to make it explicit:proto does not hide
xandfnbut its not that easy to access them by mistake since you must usep$xandp$fn()to access them which is not really that different than being able to writee <- environment(example); e$hidden.fn()EDIT:
The object oriented approach does add the possibility of inheritance, e.g. one could define a child of
pwhich acts likepexcept that it overridesfn.