--- title: "Expressions and Variables" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Expressions and Variables} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ## Introduction When you call `$run(expr)`, the calling environment is not visible to `expr`. Therefore, all variables needed by `expr` must be explicitly provided to `$run(vars = list())` or previously set in the `jobqueue(globals = list())` constructor. ## Expressions The `expr` parameter can be given in two ways. * `expr = { 42 }` * `expr = quote({ 42 })` The second form is helpful if your expression needs to be passed around your own code before being handed off to `$run()`. Other call-generating functions can be used instead of `quote()`, such as `call()` or `bquote()`. ```r library(jobqueue) jq <- jobqueue() jq$run({ 42 })$result #> [1] 42 expr <- quote({ 42 }) jq$run(expr)$result #> [1] 42 ``` ## Variables Global variables can be set when the `jobqueue` is created. ```r globals <- list(MY_DATA = mtcars) jq <- jobqueue(globals = globals) expr <- quote(colnames(MY_DATA)) jq$run(expr)$result[1:6] #> [1] "mpg" "cyl" "disp" "hp" "drat" "wt" ``` Additional variables for a `job` can be defined with `$run(vars = list())`. ```r expr <- quote(MY_DATA[rows,cols]) vars <- list(rows = 20:22, cols = c('mpg', 'hp', 'wt')) jq$run(expr = expr, vars = vars)$result #> mpg hp wt #> Toyota Corolla 33.9 65 1.835 #> Toyota Corona 21.5 97 2.465 #> Dodge Challenger 15.5 150 3.520 ``` ## Functions The remote environment inherits from R's `baseenv()`, so you can call base functions as usual. ```r jq$run({ rep(2, 5) })$result #> [1] 2 2 2 2 2 ``` To use a function from a package, call it with `::` notation. ```r jq$run({ jsonlite::toJSON(list(x = 42)) })$result #> {"x":[42]} ``` To use a custom function, pass it like a variable. ```r f <- function (x) x * 2 jq$run({ f(x) }, vars = list(f=f, x=5))$result #> [1] 10 ``` But remember, like `expr`, functions do not have access to the local environment. ```r x <- 5 f <- function () x * 2 f() #> [1] 10 jq$run({ f() }, vars = list(f=f))$result #> ``` Functions from packages are the exception - they retain access to their namespace when passed as a variable. ```r x <- list(x = 42) f <- jsonlite::toJSON jq$run({ f(x) }, vars = list(f=f, x=x))$result #> {"x":[42]} ``` If you're using a lot of functions from a package, you can set `jobqueue(packages = '')`, then call that package's functions without the `::` notation. If you're a package developer, you can set `jobqueue(namespace = '')` to give the remote environment access to all functions and variables (both exported and non-exported) defined in your package's namespace. Note however that your package must be installed for changes to take effect in the remote environment. I.e. `devtools::load_all()` won't cut it; an `R CMD INSTALL` is needed (via `devtools::install()`, `pak::install_local()`, etc). ## Example ```r library(jobqueue) jq <- jobqueue( globals = list(A = 1), init = { B <- 12 }, packages = 'jsonlite' ) job <- jq$run( 'vars' = list(x = 37), 'expr' = { toJSON(c(A, B, x)) } ) job$result #> [1,12,37] ``` Here we defined two global variables: `A` and `B`. We also attached the 'jsonlite' R package to the search path. When `expr` is evaluated, it uses `toJSON`, `A`, and `B` from the remote environment, and `x` from `vars`.