Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Define an anonymous function without using the `function` keyword

I can define and use an anonymous function and call it like this

x <- 1:3
sapply(x, function(x) x)

Sometimes I feel that using function like this is too verbose. Is there another way to define an anonymous function?

In the purrr package, one can define an anonymous function like this

map(x, ~.x)

but this only works in the purrr context.

like image 225
xiaodai Avatar asked Sep 25 '18 07:09

xiaodai


2 Answers

How less verbose could you make it? You need some kind of indicator that this is a function, some way of saying the arguments, and some way of saying the calculation. The only thing that makes it "verbose" is that "function" has eight letters. If you don't want that then define your function outside the apply and then you get sapply(x, foo) which is concise and descriptive and well-understood without resort to external dependencies (purrrr) or non-standard evaluation.

like image 142
Spacedman Avatar answered Sep 20 '22 23:09

Spacedman


1) gsubfn::fn The gsubfn package supports a formula notation for defining functions and unlike purrr, mentioned in the question, which only works with purrr functions it works with just about any function.

If an anonymous function is passed to another function, in the example the anonymous function is passed to sapply, then preface sapply with fn$ and use formula notation of the form args ~ body. If args are missing then the free variables in the body are assumed to be arguments in the order encountered in the body so in the first example below z is assumed to be the single argument.

library(gsubfn)

x <- 1:3
fn$sapply(x, ~ z)
## [1] 1 2 3

# same - specify arg
fn$sapply(x, z ~ z)
## [1] 1 2 3

# same - can use any variable name we like
fn$sapply(x, ~ x)
## [1] 1 2 3

# same
sapply(x, function(z) z)
## [1] 1 2 3

Anonymous functions can have any number of arguments. The following are all the same:

fn$sapply(x, ~ u + 2 * v, v = 10)
## [1] 21 22 23

# same
fn$sapply(x, u + v ~ u + 2 * v, v = 10)
## [1] 21 22 23

# same
sapply(x, function(u, v) u + 2 * v, v = 10)
## [1] 21 22 23

2) magrittr

The magrittr package supports a pipe notation for defining single argument functions. The argument must be dot.

library(magrittr)

x <- 1:3
sapply(x, . %>% {.})
## [1] 1 2 3

# same
sapply(x, function(x) x)
## [1] 1 2 3

# same
x %>% sapply(. %>% {.})
## [1] 1 2 3

3) lambda.r The lambda.r package allows one to define named functions using %as%. Here we define a function named fun.

library(lambda.r)

x <- 1:3
fun(x) %as% x
sapply(x, fun)
## [1] 1 2 3

# same
fun <- function(x) x
sapply(x, fun)
## [1] 1 2 3
like image 38
G. Grothendieck Avatar answered Sep 21 '22 23:09

G. Grothendieck