简体   繁体   中英

Making variables immutable in R

If I try to set NA or another special variable in RI get a nice warning:

> NA <- 1

Error in NA <- 1 : invalid (do_set) left-hand side to assignment

Is it possible to achieve the same with variables defined in my own code?

I tried to use lockBinding('foo', parent.env(environment()) inside my package .onLoad() but that will happily allow me to shadow the locked binding.

To expand:

In a package myPackage I can create the following init.R file:

#' @export
foo <- 1

.onLoad <- function(libname, pkgname) {
  lockBinding('foo', parent.env(environment()))
}

devtools::document() and R CMD INSTALL it and now do:

> library(myPackage)
> foo
[1] 1
> foo <- 2
> foo
[1] 2
> myPackage::foo
[1] 1
> rm(foo)
> foo
[1] 1 

I want to make it so that foo doesn't get shadowed (like NA can't be).

There's no way to get the same effect as with reserved names. A reserved name simply cannot be shadowed (you can assign to `NA` but it never shadows NA — evaluating NA simply never performs a variable lookup). Whereas variables always can.

Incidentally, your lockBinding call in .onLoad is redundant: Bindings for package symbols are locked by default.

You could override <- , this would be a very bad idea in general if done in the global environment, but done in a specific environement if you know what you're doing why not :

X <- new.env()
X$`<-` <- function(e1, e2) {
  sc <- sys.call()
  if(identical(sc[[2]], quote(foo)))
     stop("invalid left-hand side to assignment")
  else
    eval.parent(do.call(substitute, list(sc, list(`<-` = base::`<-`))))
}

with(X, foo <- 42)
#> Error in foo <- 42: invalid left-hand side to assignment
with(X, bar <- 42)
X$bar
#> [1] 42

Created on 2019-08-19 by the reprex package (v0.3.0)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM