Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WISH/ROBUSTNESS: Mechanism to prevent var <<- value from assigning non-existing 'var' #147

Open
HenrikBengtsson opened this issue Mar 19, 2023 · 1 comment
Labels
code robustess on r-devel or r-pkg-devel mailing lists Issue has been raised on the R-devel or R-pkg-devel mailing lists r-dev-day-candidate r-language

Comments

@HenrikBengtsson
Copy link
Owner

HenrikBengtsson commented Mar 19, 2023

Wish

I'd like to be able to prevent the <<- assignment operator 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 <<- falls 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 permanently. 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 environment, could use assign(var, value, envir = globalenv()) or globalenv()[[var]] <- value. That would also make it explicit where the variable is assigned.

R CMD check could temporarily set check.superassignment = TRUE during checks to improve its current checks for assignments to the global environment. Moreover, 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 R script under the "strict" behavior.

@HenrikBengtsson
Copy link
Owner Author

I've sent this proposal to R-devel thread 'WISH: Optional mechanism preventing var <<- value from assigning non-existing variable' on 2023-03-19 (https://stat.ethz.ch/pipermail/r-devel/2023-March/082472.html).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
code robustess on r-devel or r-pkg-devel mailing lists Issue has been raised on the R-devel or R-pkg-devel mailing lists r-dev-day-candidate r-language
Projects
None yet
Development

No branches or pull requests

1 participant