DEV Community

Colin Fay
Colin Fay

Posted on • Originally published at colinfay.me on

1 2

JavaScript cont in R

One thing I like about JavaScript is the const declaration method, which allows you to declare a variable one time, and that variable can’t be reassigned after that. I.e, this piece of code will throw an error:

node -e "const x = 12; x = 14"


## [eval]:1
## const x = 12; x = 14
## ^
## 
## TypeError: Assignment to constant variable.
## at [eval]:1:18
## at Script.runInThisContext (vm.js:124:20)
## at Object.runInThisContext (vm.js:314:38)
## at Object.<anonymous> ([eval]-wrapper:9:26)
## at Module._compile (internal/modules/cjs/loader.js:805:30)
## at evalScript (internal/process/execution.js:60:25)
## at internal/main/eval_string.js:16:1

Enter fullscreen mode Exit fullscreen mode

The cool thing about this is that you can’t override the variable by mistake: once it’s set, it’s set. On the other hand, R allows you to override almost any variable (well, except some reserved variables).

I asked Twitter if there was any implementation of that concept in R.The use case, for example, would arise when you have a value that takes some time to compute. If I do my computation, I can accidentally override it later on. Event more if you’re using notebook, where you create symbols and values all along your document.

a <- some_very_complex_computation()
# [...] Going on the weekend
a <- "Hello there!"

Enter fullscreen mode Exit fullscreen mode

Here, I have no way to prevent myself from erasing the value in a. Of course, there are always rigour, explicit variable name, and not-assigning-things-without-thinking but you know how it is in the real world, and there is no Cmd + Z there.

Romain pointed out that ?lockBinding existed, and that it was what I was looking for. And that does.

Here’s how it works: it takes a character string referring to a symbol, and an environment, and prevents from assigning any new value to this symbol in the given environment.

x <- 12
lockBinding("x", .GlobalEnv)
x <- 13


## Error in eval(expr, envir, enclos): cannot change value of locked binding for 'x'

Enter fullscreen mode Exit fullscreen mode

And here’s a small wrapper to do that:

lock <- function(x){
  lockBinding(
    deparse(
      substitute(x)), 
    env = parent.frame()
  )
}

plop <- 12
lock(plop)
plop <- 13


## Error in eval(expr, envir, enclos): cannot change value of locked binding for 'plop'


pouet <- function(){
  plop <- 14
  print(plop)
  lock(plop)
  plop <- 13
}
pouet()


## [1] 14

## Error in pouet(): cannot change value of locked binding for 'plop'

Enter fullscreen mode Exit fullscreen mode

So there I could do

a <- some_very_complex_computation()
lock(a)
# [...] Going on the weekend
a <- "Hello there!"

Enter fullscreen mode Exit fullscreen mode

And there, I have prevented myself from erasing my a variable. Ofcourse, it’s not the same as JavaScript const, as there is always away to unlock the symbol.

x <- 12


## Error in eval(expr, envir, enclos): cannot change value of locked binding for 'x'


lock(x)
x <- 13


## Error in eval(expr, envir, enclos): cannot change value of locked binding for 'x'


unlockBinding("x", .GlobalEnv)
x <- 13
x


## [1] 13

Enter fullscreen mode Exit fullscreen mode

But I think it’s a rather elegant solution for preventing yourself fromunwanted variable overwriting.

See also:

Some answers to the Twitter thread also suggested using R6… but that will be for another post :)

Heroku

Simplify your DevOps and maximize your time.

Since 2007, Heroku has been the go-to platform for developers as it monitors uptime, performance, and infrastructure concerns, allowing you to focus on writing code.

Learn More

Top comments (0)

AWS Security LIVE!

Join us for AWS Security LIVE!

Discover the future of cloud security. Tune in live for trends, tips, and solutions from AWS and AWS Partners.

Learn More

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay