# Anonymous Functions, Part II: gsubfn

gsubfn's as.function and fn$* notation

*This is a follow-up to* Anonymous Functions, Not Variables.
*For context, read that first.*

After my previous post, Brodie Gaslam pointed me in an interesting direction on Twitter:

Have you seen https://t.co/KTChI5NMYb as.function.formula? Very similar concepts.

— BrodieG (@BrodieGaslam) March 26, 2018

He’s right. Gabor Grothendieck’s gsubfn
package is centered
around its `gsubfn`

function, an extended version of `gsub`

whose `replacement`

parameter can accept functions, e.g. to do arithmetic with numbers in a string.

That anonymous function can be written as a formula, a capability enabled by a
`as.function.formula`

function which is also exported. It provides very similar
functionality to the `lambda`

function I defined, so the nested `map`

example
could be written

```
library(purrr)
map(c("a", "b", "c"),
gsubfn::as.function.formula(x ~ map_chr(1:3,
gsubfn::as.function.formula(y ~ paste0(x, y))))) %>%
str()
#> List of 3
#> $ : chr [1:3] "a1" "a2" "a3"
#> $ : chr [1:3] "b1" "b2" "b3"
#> $ : chr [1:3] "c1" "c2" "c3"
```

As it appears, it is a method for the S3 generic `base::as.function`

, so when
gsubfn is loaded, the syntax can be condensed to

```
library(gsubfn)
#> Loading required package: proto
map(c("a", "b", "c"),
as.function(x ~ map_chr(1:3,
as.function(y ~ paste0(x, y))))) %>%
str()
#> List of 3
#> $ : chr [1:3] "a1" "a2" "a3"
#> $ : chr [1:3] "b1" "b2" "b3"
#> $ : chr [1:3] "c1" "c2" "c3"
```

and the generic will dispatch to it when passed a formula.

The best part of `gsubfn::as.function.formula`

, though, is the alternative way
it can be called. At the end of the previous post, I concluded

Ideally, it would be nice to drop the

`lambda`

call altogether, but as far as I have been able to find, the only way to do so would be to redefine`purrr:::as_mapper.default`

to call`lambda`

instead of`rlang::as_closure`

when passed a formula with anything on the left-hand side.For now, then, extra keystrokes abide.

But `gsubfn`

has found a clever way to minimize keystrokes. It defines an `fn`

object with its own class. That class has a method for `$`

that is rather
different than its usual subsetting duties. Instead, it takes a call with a
formula in it, and returns that call with the formula converted to a function
by `as.function.formula`

(with some safeguards to ignore actual formulas). So
while it looks a little weird, at first, you can write

```
fn$sapply(1:3,
i ~ paste0(letters[i], i))
#> [1] "a1" "b2" "c3"
fn$map2_chr(letters[1:3],
1:3,
l + n ~ paste0(l, n))
#> [1] "a1" "b2" "c3"
```

or for the nested `map`

example,

```
fn$map(c("a", "b", "c"),
x ~ fn$map_chr(1:3,
y ~ paste0(x, y))) %>%
str()
#> List of 3
#> $ : chr [1:3] "a1" "a2" "a3"
#> $ : chr [1:3] "b1" "b2" "b3"
#> $ : chr [1:3] "c1" "c2" "c3"
```

effectively modifying functions on the fly to accept full formula lambda notation in a beautiful bit of code.

## Share this post