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

findGlobals() chooses to be conservative when a variable is a global conditionally #31

Open
HenrikBengtsson opened this issue Dec 20, 2017 · 4 comments

Comments

@HenrikBengtsson
Copy link
Collaborator

Issue

findGlobals() choose to be conservative when a variable is a global conditionally on a run-time variable/value:

> findGlobals({ if (runif(1) < 1/2) y <- 0; y }, substitute = TRUE)
[1] "{"     "if"    "<"     "runif" "/"     "<-"

Here we probably want to pick up y as a global variable too.

I'm acknowledging that such ambiguous expression should be avoid, but we still might want to support them, and there might be cases where it could be argued for. Maybe the following is an example:

foo <- function(x, resample = FALSE) {
  idxs <- slow_creation_of_indices(x)  ## Make only once
  future_lapply(x, FUN = function(z) {
     if (resample) idxs <- sample(idxs)
     z[c(1,length(z))]
  })
}

Though it could be argued that what is really used here is:

foo <- function(x, resample = FALSE) {
  idxs0 <- slow_creation_of_indices(x)  ## Make only once
  future_lapply(x, FUN = function(z) {
     if (resample) idxs <- sample(idxs0) else idxs <- idxs0
     z[c(1,length(z))]
  })
}
@HenrikBengtsson
Copy link
Collaborator Author

HenrikBengtsson commented Dec 21, 2017

Here's a miminal reproducible example that illustrates the problem and that can be used as a test case (in the future package).

library("future")
plan(multisession, workers = 2L)

reset <- TRUE
x <- 1
y %<-% { if (reset) x <- 0; x + 1 }
y
## [1] 1

reset <- FALSE
x <- 1
y %<-% { if (reset) x <- 0; x + 1 }
y
## Error: object 'x' not found

@HenrikBengtsson
Copy link
Collaborator Author

And for the record:

## Default
> globals::findGlobals({ if (reset) x <- 0; x + 1 }, method = "ordered", substitute = TRUE)
[1] "{"     "if"    "reset" "<-"    "+"    

> globals::findGlobals({ if (reset) x <- 0; x + 1 }, method = "conservative", substitute = TRUE)
[1] "{"     "if"    "reset" "<-"    "+"    

> globals::findGlobals({ if (reset) x <- 0; x + 1 }, method = "liberal", substitute = TRUE)
[1] "{"     "if"    "reset" "<-"    "+"     "x"    

@HenrikBengtsson
Copy link
Collaborator Author

HenrikBengtsson commented Dec 30, 2017

Branch feature/if-ambiguity now has an initial prototype for handling this, e.g.

> globals::findGlobals({ if (reset) x <- 0; x + 1 }, method = "ordered", substitute = TRUE)
[1] "{"     "if"    "x"     "reset" "<-"    "+"

However, this does not appear to work when inside a function, e.g.

> globals::findGlobals(function() { if (reset) x <- 0; x + 1 }, method = "ordered", substitute = TRUE)
[1] "{"     "if"    "reset" "<-"    "+"

so more work is needed.

@HenrikBengtsson
Copy link
Collaborator Author

Previously, I've found one example of this in the caret package, and just now another example in the phylolm package (variable MLEsigma2_error).

@HenrikBengtsson HenrikBengtsson changed the title findGlobals() choose to be conservative when a variable is a global conditionally findGlobals() chooses to be conservative when a variable is a global conditionally May 2, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant