---
title: "eply"
author: "William Michael Landau"
date: "`r Sys.Date()`"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{eply}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

The `eply` package processes batches of quoted expressions. Just as `apply()` acts on data frames of function arguments, `eply()` acts on data frames of quoted **expressions** that **return** arguments. The package also has `evals()`, which simply evaluates a character vector of quoted expressions, plus some nice utilities.

# Function `eply()`

```{r}
library(eply)
```

`eply()` applies a function over a data frame of quoted expressions.

Begin with a function.
```{r}
.fun = example.fun
.fun
```

Then, make a data frame of quoted expressions that return arguments to `.fun`.
```{r}
.expr = example.expr()
.expr
# str(.expr) # The expressions are actually just characters.
```

Define the variables referenced in `.expr`.
```{r}
a = 1
b = 2
```

For each row in `.expr`, `eply()` evaluates the expressions and feeds the results to `.fun`.

```{r}
eply(.fun, .expr)
```

# Function `evals()`

`evals()` evaluates a character vector of quoted expressions.

```{r}
evals(c("1+1", "2+2", "3+3"))
evals(c("1+1", "2+2", "3+3"), .simplify = FALSE)
a = 4
evals(c("subset(mtcars, cyl == a, mpg, TRUE)", "mtcars[1:2, 1:2]"))
```

# Control the evaluation environment

Use the `.with` argument to control the environment in which the expressions are evaluated. `.with` can be a list, data frame, or environment. Data in the calling environment may be used as well, so take care to avoid ambiguities. 

```{r}
.fun = function(x) return(x)
.expr = data.frame(x = c("1+a", "1+b"))
rownames(.expr) = c("expr1", "expr2")
a = b = 0
.with = list(a = 1, b = 2)
eply(.fun, .expr, .with)
evals(.expr$x, .with)
```

The `.with` argument is especially important if you wish to pass `eply()` or `evals()` to an iteration function like `lapply()`.

```{r}
.expr2 = split(.expr, f = .expr$x) # list of rows of .expr
lapply(.expr2, eply, .fun = .fun, .with = .with)
lapply(c("1+X", "2+Y"), evals, .with = list(X = 1, Y = 2))
```


# Parallel execution

Eply does not implement any special parallel computing functionality. However, the `parallel` package may be used on non-Windows machines to distribute subsets of `.expr` across parallel processes. The output of `parallel::mclapply()` is a list, so take care to simplify if necessary (say, to a data frame).

```{r, eval = F}
library(parallel)
.fun = example.fun
expr.dataframe = example.expr()
expr.list = split(expr.dataframe, f = expr.dataframe$rep) # split expr.dataframe by rep
.with = example.with()
mclapply(X = expr.list, FUN = eply, .fun = .fun, .with = .with, mc.cores = 2)
```

The parallel execution of `evals()` with `mclapply()` is similar. For an alternative, consider the [`plyr`](http://seananderson.ca/2013/12/01/plyr.html)
package to parallelize `eply()` over chunks of `.expr`. See the
["Parallel processing"](http://seananderson.ca/2013/12/01/plyr.html#parallel-processing) section of the linked guide.


# Character vector manipulation

If you want some quoted expressions to evaluate to character strings, enclosed them with literal escaped quotes.

```{r}
.expr = data.frame(
  string = quotes(c("a", "b")),
  variable = c("c", "d"))
.expr
.fun = function(string, variable) paste(string, variable)
.with = list(c = "C", d = "D")
eply(.fun, .expr, .with)
```

You can use single or double quotes.

```{r}
quotes(c("x", "y"))
quotes(c("x", "y"), single = FALSE)
quotes(c("x", "y"), single = TRUE)
```

Undo with `unquote()`.

```{r}
.expr$string = unquote(.expr$string)
.expr
x = quotes(quotes(c("x", "y"), single = TRUE))
x
unquote(x, deep = TRUE)
unquote(x, deep = FALSE)
```

Turn valid expressions into strings with `strings()`.

```{r}
data.frame(
  arg1 = strings(a + b, sqrt(x) - 2), 
  arg2 = 1:2)
```

# More help

```{r}
help_eply()
```

