---
title: "Expressions and Variables"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Expressions and Variables}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---



## Introduction

When you call `<jobqueue>$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 `<jobqueue>$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
#> <simpleError in f(): object 'x' not found>
```

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 = '<packageName>')`, then call that package's functions 
without the `::` notation.

If you're a package developer, you can set 
`jobqueue(namespace = '<yourPackageName>')` 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`.
