[Rd] WISH: Optional mechanism preventing var <<- value from assigning non-existing variable

Duncan Murdoch murdoch@dunc@n @end|ng |rom gm@||@com
Sun Mar 19 18:53:57 CET 2023


I think that should be the default behaviour. It's pretty late to get 
that into R 4.3.0, but I think your proposal (with check.superassignment 
= FALSE being the default) could make it in, and 4.4.0 could change the 
default to TRUE.

Duncan



On 19/03/2023 12:08 p.m., Henrik Bengtsson wrote:
> I'd like to be able to prevent the <<- assignment operator ("super
> assignment") from assigning to the global environment unless the
> variable already exists and is not locked.  If it does not exist or is
> locked, I'd like an error to be produced.  This would allow me to
> evaluate expressions with this temporarily set to protect against
> mistakes.
> 
> For example, I'd like to do something like:
> 
> $ R --vanilla
>> exists("a")
> [1] FALSE
> 
>> options(check.superassignment = TRUE)
>> local({ a <<- 1 })
> Error: object 'a' not found
> 
>> a <- 0
>> local({ a <<- 1 })
>> a
> [1] 1
> 
>> rm("a")
>> options(check.superassignment = FALSE)
>> local({ a <<- 1 })
>> exists("a")
> [1] TRUE
> 
> 
> BACKGROUND:
> 
>  From help("<<-") we have:
> 
> "The operators <<- and ->> are normally only used in functions, and
> cause a search to be made through parent environments for an existing
> definition of the variable being assigned. If such a variable is found
> (and its binding is not locked) then its value is redefined, otherwise
> assignment takes place in the global environment."
> 
> I argue that it's unfortunate that <<- fallbacks back to assigning to
> the global environment if the variable does not already exist.
> Unfortunately, it has become a "go to" solution for many to use it
> that way.  Sometimes it is intended, sometimes it's a mistake.  We
> find it also in R packages on CRAN, even if 'R CMD check' tries to
> detect when it happens (but it's limited to do so from run-time
> examples and tests).
> 
> It's probably too widely used for us to change to a more strict
> behavior permanent.  The proposed R option allows me, as a developer,
> to evaluate an R expression with the strict behavior, especially if I
> don't trust the code.
> 
> With 'check.superassignment = TRUE' set, a developer would have to
> first declare the variable in the global environment for <<- to assign
> there.  This would remove the fallback "If such a variable is found
> (and its binding is not locked) then its value is redefined, otherwise
> assignment takes place in the global environment" in the current
> design.  For those who truly intends to assign to the global, could
> use assign(var, value, envir = globalenv()) or globalenv()[[var]] <-
> value.
> 
> 'R CMD check' could temporarily set 'check.superassignment = TRUE'
> during checks.  If we let environment variable
> 'R_CHECK_SUPERASSIGNMENT' set the default value of option
> 'check.superassignment' on R startup, it would be possible to check
> packages optionally this way, but also to run any "non-trusted" R
> script in the "strict" mode.
> 
> 
> TEASER:
> 
> Here's an example why using <<- for assigning to the global
> environment is a bad idea:
> 
> This works:
> 
> $ R --vanilla
>> y <- lapply(1:3, function(x) { if (x > 2) keep <<- x; x^2 })
>> keep
>> [1] 3
> 
> 
> This doesn't work:
> 
> $ R --vanilla
>> library(purrr)
>> y <- lapply(1:3, function(x) { if (x > 2) keep <<- x; x^2 })
> Error in keep <<- x : cannot change value of locked binding for 'keep'
> 
> 
> But, if we "declare" the variable first, it works:
> 
> $ R --vanilla
>> library(purrr)
>> keep <- 0
>> y <- lapply(1:3, function(x) { if (x > 2) keep <<- x; x^2 })
>> keep
>> [1] 3
> 
> /Henrik
> 
> PS. Does the <<- operator have an official name? Hadley calls it
> "super assignment" in 'Advanced R'
> (https://adv-r.hadley.nz/environments.html), which is where I got it
> from.
> 
> ______________________________________________
> R-devel using r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel



More information about the R-devel mailing list