Dies ist eine Erweiterung der Diskussion here.
Unsere drei Teile müssen eine Argumentliste, ein Körper und eine Umgebung sein.
Für die Umwelt werden wir einfach env = parent.frame()
standardmäßig verwenden.
wir nicht wirklich eine regelmäßige alte Liste für die Argumente wollen, so verwenden Sie stattdessen wir alist
, die etwas anderes Verhalten hat:
“... Werte nicht bewertet werden, und getaggt Argumente ohne Wert
args <- alist(a = 1, b = 2)
Für den Körper ist „
erlaubt, wir
quote
unseren Ausdruck ein
call
zu bekommen:
body <- quote(a + b)
Eine Option ist args
zu einem pairlist zu konvertieren und dann rufen Sie einfach die Funktion function
eval
mit:
make_function1 <- function(args, body, env = parent.frame()) {
args <- as.pairlist(args)
eval(call("function", args, body), env)
}
Eine weitere Option eine leere Funktion, ist zu erstellen und es dann mit den gewünschten Werten füllen:
make_function2 <- function(args, body, env = parent.frame()) {
f <- function() {}
formals(f) <- args
body(f) <- body
environment(f) <- env
f
}
Eine dritte Möglichkeit ist einfach zu verwenden as.function
:
make_function3 <- function(args, body, env = parent.frame()) {
as.function(c(args, body), env)
}
Und schließlich scheint dies sehr ähnlich das erste Verfahren zu mir, außer wir ein etwas anderes Idiom werden mit dem Funktionsaufruf zu erstellen, mit substitute
statt call
:
make_function4 <- function(args, body, env = parent.frame()) {
subs <- list(args = as.pairlist(args), body = body)
eval(substitute(`function`(args, body), subs), env)
}
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 187 273.5 309.0 363.0 673
2 make_function1(args, body) 4123 4729.5 5236.0 5864.0 13449
3 make_function2(args, body) 50695 52296.0 53423.0 54782.5 147062
4 make_function3(args, body) 8427 8992.0 9618.5 9957.0 14857
5 make_function4(args, body) 5339 6089.5 6867.5 7301.5 55137
Ich denke, das ist, warum sie Lisps erfunden! – Justin
seltsam, wie es klingen mag, wir haben einen Fall gesehen, in dem man [string] eine Zeichenfolge (http://stackoverflow.com/q/9345373/471093) haben möchte, um etwas Ähnliches (knitr) zu erreichen. – baptiste