これは、ここでの議論の拡張です。
3 つの部分は、引数リスト、本体、および環境である必要があります。
環境については、デフォルトで単純に使用env = parent.frame()
します。
引数に通常の古いリストは必要ないので、代わりに、alist
動作が異なる whichを使用します。
「...値は評価されず、値のないタグ付き引数は許可されます」
args <- alist(a = 1, b = 2)
ボディについては、次quote
の式を取得しcall
ます。
body <- quote(a + b)
1 つのオプションは、ペアリストに変換してから、以下を
使用してargs
単純に関数を呼び出すことです。function
eval
make_function1 <- function(args, body, env = parent.frame()) {
args <- as.pairlist(args)
eval(call("function", args, body), env)
}
もう 1 つのオプションは、空の関数を作成してから、必要な値を入力することです。
make_function2 <- function(args, body, env = parent.frame()) {
f <- function() {}
formals(f) <- args
body(f) <- body
environment(f) <- env
f
}
3 番目のオプションは、次のように単純に使用することas.function
です。
make_function3 <- function(args, body, env = parent.frame()) {
as.function(c(args, body), env)
}
そして最後に、これは私には最初の方法と非常に似ているように見えますが、関数呼び出しを作成するために多少異なるイディオムを使用していることを除いて、
substitute
ではなくを使用してい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