# Easy lambdas

`R`

already has anonymous functions. Just write `function(x) do_someting`

and
you’re done. This post is for all of us who are not satisified with this
solution. For one, it’s exhausting to write to long `function(x)`

instead of,
say, `L(x)`

, but that’s not all of it!

Take the following example, a calculation of the maximum likelihood estimate of a gamma distribution:

```
set.seed(313)
x = rgamma(100, 2, 4)
nlm(f = function(p) -mean(dgamma(x, shape = p[1], rate = p[2], log = TRUE)),
p = c(1, 1))$estimate
```

`## [1] 2.138694 4.223359`

Here the hassle is to keep track of the indices of `p`

, which is not even needed
as a variable name. The function argument of `nlm`

works perfectly well with
no named arguments!

In this post I will introduce the L-function, which allows you to write the previous function call like this:

```
nlm(f = L(-mean(dgamma(x, shape = ?1, rate = ?2, log = TRUE))),
p = c(1, 1))
```

The function created by L doesn’t have any named arguments, but you can refer to
the unnamed arguments by the question mark. Actually, the function `f`

above is
equivalent to the following, just with some syntactic sugar on top.

`function(...) -mean(dgamma(x, ...[[1]], ...[[2]], log = TRUE)))`

This works in the `nlm`

case since whenever `f`

has the signature `...`

and
receives a vector, it interprets this as `do.call`

over the vector:

```
f = function(...) ...[[1]]
f(c(1, 2, 3))
```

`## [1] 1`

The consequence is that functions that depend on vectorization (e.g.
`integrate`

) won’t work together with L.

### The L function

```
call_replace = function(call) {
if(length(call) > 1) {
if(call[[1]] == quote(`?`))
if(is.numeric(call[[2]]))
return(parse(text = paste0("...[[", eval(call[[2]]), "]]"))[[1]])
new = as.call(lapply(1:length(call), function(i) call_replace(call[[i]])))
names(new) = names(call)
new
} else call
}
L = function(call, quoted = FALSE) {
call = if(!quoted) substitute(call) else call
f = function(...) NULL
body(f) = call_replace(call)
environment(f) = parent.frame()
f
}
```

What does it do? First, `call_replace`

travels recursively through the call and
replaces any instance of `?n`

with `...[[n]]`

. The `L`

constructs a function
from the modified call.

### Using magrittr

It’s also possible to make a piped version of this:

```
library("magrittr")
`%L>%` = function(lhs, rhs) {
lhs_call = call(name = "function",
quote(function(...) {})[[2]],
call_replace(substitute(lhs)))
rhs_call = substitute(rhs)
eval(call("%>%", lhs_call, rhs_call))
}
-mean(dgamma(x, shape = ?1, rate = ?2, log = TRUE)) %L>%
nlm(p = c(1, 1)) %$%
estimate
```

`## [1] 2.138694 4.223359`

This piped version won’t work if it is placed in the middle of a magrittr pipe. Take this example:

```
rgamma(100, 2, 7) %>%
-mean(dgamma(shape = ?1, rate = ?2, log = TRUE)) %L>%
nlm(p = c(1, 1))
```

`## Error in dgamma(shape = ...[[1]], rate = ...[[2]], log = TRUE): argument "x" is missing, with no default`

### Ideas to modify L

We could use `!n`

to reference the \(n\)th argument of the created function.
Moreover, they could be named and given default values. The propotype
`L(f(a = !1 == b <- c, 1, 2, 3))`

will return a function of one argument named
`b`

with default value `c`

.