# fn: Function Declarations with Quasiquotation In gestalt: Tools for Making and Combining Functions

## Description

`fn()` enables you to create (anonymous) functions, of arbitrary call signature. Use it in place of the usual `function()` invocation whenever you want to:

• Be concise: The function declarations

```  fn(x, y = 1 ~ x + y)

function(x, y = 1) x + y
```

are equivalent.

• Enforce immutability: By enabling Tidyverse quasiquotation, `fn()` allows you to “burn in” values at the point of function creation. This guards against changes in a function's enclosing environment. (See ‘Use Unquoting to Make Robust Functions’.)

`fn_()` is a variant of `fn()` that does not comprehend quasiquotation. It is useful when you want unquoting (``!!``) or splicing (``!!!``) operators in the function body to be literally interpreted, rather than immediately invoked. (See ‘Quasiquotation’ for a complementary way to literally interpret unquoting and splicing operators in `fn()`.)

## Usage

 ```1 2 3``` ```fn(..., ..env = parent.frame()) fn_(..., ..env = parent.frame()) ```

## Arguments

 `...` Function declaration, which supports quasiquotation. `..env` Environment in which to create the function (i.e., the function's enclosing environment).

## Value

A function whose enclosing environment is `..env`.

## Function Declarations

A function declaration is an expression that specifies a function's arguments and body, as a comma-separated expression of the form

 `1` ``` arg1, arg2, ..., argN ~ body ```

or

 `1` ``` arg1, arg2, ..., argN, ~body ```

(Note in the second form that the body is a one-sided formula. This distinction is relevant for argument splicing, see ‘Quasiquotation’.)

• To the left of `~`, you write a conventional function-argument declaration, just as in `function(<arguments>)`: each of `arg1`, `arg2`, ..., `argN` is either a bare argument (e.g., `x` or `...`) or an argument with default value (e.g., `x = 1`).

• To the right of `~`, you write the function body, i.e., an expression of the arguments.

## Quasiquotation

All parts of a function declaration support Tidyverse quasiquotation:

• To unquote values (of arguments or parts of the body), use `!!`:

```  z <- 0
fn(x, y = !!z ~ x + y)
fn(x ~ x > !!z)
```
• To unquote argument names (with default value), use `:=` (definition operator):

```  arg <- "y"
fn(x, !!arg := 0 ~ x + !!as.name(arg))
```
• To splice in a (formal) list of arguments, use `!!!`:

```  # NB: Body is a one-sided formula
fn(!!!alist(x, y = 0), ~ x + y)
```

Splicing allows you to treat a complete function declaration as a unit:

```  soma <- alist(x, y = 0, ~ x + y)
fn(!!!soma)
```
• To write literal unquoting operators, use `QUQ()`, `QUQS()`, which read as “quoted unquoting,” “quoted unquote-splicing,” resp. (cf. `fn_()`):

```  library(dplyr)

my_summarise <- fn(df, ... ~ {
group_by <- quos(...)
df %>%
group_by(QUQS(group_by)) %>%
summarise(a = mean(a))
})
```

(Source: Programming with dplyr)

## Use Unquoting to Make Robust Functions

Functions in R are generally impure, i.e., the return value of a function will not in general be determined by the value of its inputs alone. This is because, by design, a function may depend on objects in its lexical scope, and these objects may mutate between function calls. Normally this isn't a hazard.

However, if you are working interactively and sourcing files into the global environment, or using a notebook interface like Jupyter or R Notebook, it can be tricky to ensure that you haven't unwittingly mutated an object that an earlier function depends upon.

You can use unquoting to guard against such mutations.

#### Example

Consider the following function:

 ```1 2``` ``` a <- 1 foo <- function(x) x + a ```

What is the value of `foo(1)`? It is not necessarily `2`, because the value of `a` may have changed between the creation of `foo()` and the calling of `foo(1)`:

 ```1 2 3 4 5``` ``` foo(1) #>  2 a <- 0 foo(1) #>  1 ```

In other words, `foo()` is impure because the value of `foo(x)` depends not only on the value of `x` but also on the externally mutable value of `a`.

With `fn()`, you can unquote `a` to “burn in” its value at the point of creation:

 ```1 2``` ``` a <- 1 foo <- fn(x ~ x + !!a) ```

Now `foo()` is a pure function, unaffected by changes to `a` in the lexical scope:

 ```1 2 3 4 5``` ``` foo(1) #>  2 a <- 0 foo(1) #>  2 ```

## Examples

 ``` 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52``` ```fn(x ~ x + 1) fn(x, y ~ x + y) fn(x, y = 2 ~ x + y) fn(x, y = 1, ... ~ log(x + y, ...)) # to specify '...' in the middle, write '... = ' fn(x, ... = , y ~ log(x + y, ...)) # use one-sided formula for constant functions or commands fn(~ NA) fn(~ message("!")) # unquoting is supported (using `!!` from rlang) zero <- 0 fn(x = !!zero ~ x > !!zero) # formals and function bodies can also be spliced in f <- function(x, y) x + y g <- function(y, x, ...) x - y frankenstein <- fn(!!!formals(f), ~ !!body(g)) stopifnot(identical(frankenstein, function(x, y) x - y)) # mixing unquoting and literal unquoting is possible library(dplyr) summariser <- quote(mean) my_summarise <- fn(df, ... ~ { group_by <- quos(...) df %>% group_by(QUQS(group_by)) %>% summarise(a = `!!`(summariser)(a)) }) my_summarise # Use fn_() with fn() as a concise way to force ("pin down") bindings # For example, the 'x' is immutable in the function produced by call_upon(): call_upon <- fn_(x ~ fn(f ~ f(!!x))) sapply(list(sin, cos), call_upon(0)) #  0 1 # Return-value checking, as a functional transformation enforce <- fn_(condition ~ fn(x ~ { stopifnot(!!substitute(condition)) x }) ) no_nan <- enforce(!is.nan(x)) log_strict <- fn(x ~ no_nan(log(x))) log_strict(2) #  0.6931472 log_strict(-1) # Error: !is.nan(x) is not TRUE ```

gestalt documentation built on June 27, 2019, 5:08 p.m.