[Rd] Creating functions programmatically
Hadley Wickham
h.wickham at gmail.com
Thu Oct 4 00:55:17 CEST 2012
> I think `function` does not eval its arguments, and it demands a
> pairlist. So this works:
>
> f <- eval(substitute(`function`(args, body),
> list(args=as.pairlist(alist(a=1)), body=quote(a+1))))
>
> The other thing to notice is a syntax difference between function and
> ordinary calls: when writing
Thanks.
So as far as I can tell, we have 4 basic ways of making a function
from args, body and env:
make_function1 <- function(args, body, env = parent.frame()) {
args <- as.pairlist(args)
eval(call("function", args, body), env)
}
make_function2 <- function(args, body, env = parent.frame()) {
f <- function() {}
formals(f) <- args
body(f) <- body
environment(f) <- env
f
}
make_function3 <- function(args, body, env = parent.frame()) {
as.function(c(args, body), env)
}
make_function4 <- function(args, body, env = parent.frame()) {
subs <- list(args = as.pairlist(args), body = body)
eval(substitute(`function`(args, body), subs), env)
}
args <- alist(a = 1, b = 2)
body <- quote(a + b)
make_function1(args, body)
make_function2(args, body)
make_function3(args, body)
make_function4(args, body)
And not that speed really matters much here, but:
library(microbenchmark)
microbenchmark(
make_function1(args, body),
make_function2(args, body),
make_function3(args, body),
make_function4(args, body),
function(a = 1, b = 2) a + b
)
Unit: nanoseconds
expr min lq median uq max
1 function(a = 1, b = 2) a + b 165 228 279 330 703
2 make_function1(args, body) 3540 4276 4774 5340 12947
3 make_function2(args, body) 47150 49170 49972 52510 147753
4 make_function3(args, body) 7461 8482 9116 9515 14763
5 make_function4(args, body) 4818 5814 6424 7102 13385
So constructing the call explicitly is fastest, followed by using
function, then as.function. Modifying an empty function is an order
of magnitude slower. Even the fastest approach is about 20x slower
than creating it by hand.
Hadley
--
RStudio / Rice University
http://had.co.nz/
More information about the R-devel
mailing list