Wrote this up for future_promise() usage in #62 . It did not make sense for the vignette. So I added into an issue for the time being.
## Variable scope in `future_promise()` and `future::future()`
`future_promise()` is a promise **first** and executes using `future::future()` **second**. When using `future_promise()`, you should use the same precautions that you would use with a regular `promises::promise()`.
When `future` blocks on the main R session, this prevents values from being changed before they are submitted to the external worker. While a `promise` waits to be executed, it is known that variables that have **not been `forced()`** or properly **scoped** can change from their expected values before evaluation occurs. This can also occur with properly scoped environment values as only the _pointer_ to the environment is static. This allows for the values within the environment to be altered before the `promise` is executed, which is likely undesirable.
#### Scope
In the example below, the variable `i` is not forced to a specific value for the promise. With the promise resolving within the global environment, the latest `i` value will be used for all of the promises waiting to resolve.
```r
items <- list()
for (i in 1:10) {
items <- c(items, list(
promise_resolve(TRUE) %...>% {i}
))
}
promise_all(.list = items) %...>%
{ print(unlist(.)) }
# #> [1] 10 10 10 10 10 10 10 10 10 10
To combat variable scoping issues, functions can be used to create local environments that will scope the expected i value.
Environments can have their values changed after the original promise creation. This can cause unexpected behavior when evaluating a promise.
For example, the environment env below will have its value a changed from 1 to 2 before the promise is resolved. This causes the unexpected value of 2 to be returned in the promise.
The expression in future_promise(expr) will behave like a promise and should have its volitile variables scoped and force()ed to achieve similar evaluations when using future::future() directly.
Wrote this up for future_promise() usage in #62 . It did not make sense for the vignette. So I added into an issue for the time being.
To combat variable scoping issues, functions can be used to create local environments that will scope the expected
i
value.Changing environments
Environments can have their values changed after the original promise creation. This can cause unexpected behavior when evaluating a promise.
For example, the environment
env
below will have its valuea
changed from1
to2
before the promise is resolved. This causes the unexpected value of2
to be returned in the promise.To address lazy evaluation and environment variable issues, we can store the values to a local variable and force their evaluation.
Fixing the example, we can capture the value
a
(or turn the environment into alist()
).The expression in
future_promise(expr)
will behave like a promise and should have its volitile variables scoped andforce()
ed to achieve similar evaluations when usingfuture::future()
directly.