11

Is there any way to define a variable in R in your namespace, such that it can't be overwritten (maybe ala a "Final" declaration)? Something like the following psuedocode:

> xvar <- 10
> xvar
[1] 10
xvar <- 6
> "Error, cannot overwrite this variable unless you remove its finality attribute"

Motivation: When running R scripts multiple times, it's sometimes too easy to inadvertently overwrite variables.

bigO6377
  • 1,256
  • 3
  • 14
  • 28
  • 5
    best practice in functional languages is to avoid global variables as much as possible. Use functions, changes made inside won't affect your global environment. – baptiste Feb 20 '14 at 15:25

2 Answers2

12

Check out ? lockBinding:

a <- 2
a
## [1] 2
lockBinding('a', .GlobalEnv)
a <- 3
## Error: cannot change value of locked binding for 'a'

And its complement, unlockBinding:

unlockBinding('a', .GlobalEnv)
a <- 3
a
## [1] 3
Thomas
  • 43,637
  • 12
  • 109
  • 140
  • Just beware of possible side-effects. (like accidentally unlock-bind-ing something that shouldn't ever be unlocked) – Carl Witthoft Feb 20 '14 at 16:12
  • @CarlWitthoft Seems like good advice, but do you have an example? – Thomas Feb 20 '14 at 16:14
  • If I could find it, I would :-( . Joran discussed this a week or two ago on another SO question. OTOH, it's not in the R-Inferno, so maybe I'm being overly cautious. – Carl Witthoft Feb 20 '14 at 16:19
  • ist there a way to automatically lockbind all variables that are created? and only unlockbind if needed? – titeuf Oct 04 '20 at 10:39
7

You can make variables constant using the pryr package.

install_github("pryr")
library(pryr)

xvar %<c-% 10
xvar
## [1] 10
xvar <- 6
## Error: cannot change value of locked binding for 'xvar'

The %<c-% operator is a convenience wrapper for assign + lockBinding.


Like Baptiste said in the comments: if you are having problems with this, it's a possible sign of poor coding style. Bundling the majority of your logic into functions will reduce variable name clashes.

Richie Cotton
  • 118,240
  • 47
  • 247
  • 360