我正在尝试创建一个对函数的调用,f
该函数的第一个参数是对另一个函数的调用(我选择了dbinom
作为示例(。对dbinom
的调用(传递给f
(不包括所有参数的值,因为这些值应该在f
内完成,并且完成的调用由f
返回。这是我失败的最小尝试:
f <- function(a_call) {
call_modify(a_call, x=1)
}
a_call <- call2(dbinom, size=1, prob=0.5)
y <- call2(f, a_call)
y
的输出为:
(function(a_call) {
call_modify(a_call, x=1)
})((function (x, size, prob, log = FALSE)
.Call(C_dbinom, x, size, prob, log))(size = 1, prob = 0.5))
此电话将
- 在没有任何参数的情况下调用
a_call
,然后; - 将此结果传递给
f
。
如果我评估y
,它会出错dinom
因为缺少第一个参数。
我相似但相关的结构:
> call2(call2(dbinom, x=1, size=1, prob=0.5))
((function (x, size, prob, log = FALSE)
.Call(C_dbinom, x, size, prob, log))(x = 1, size = 1, prob = 0.5))()
(function (x, size, prob, log = FALSE)
我感觉我在这里尝试的东西"甚至没有错",嵌套调用修改最好以另一种方式完成。
似乎您尝试执行的操作由purrr::partial()
更自然地处理,它填充函数的一个或多个参数:
f <- function( a_fun ) {purrr::partial( a_fun, x=1 )}
a_fun <- purrr::partial( dbinom, size=1, prob=0.5 )
y <- f(a_fun)
y(...)
现在有效地dbinom( x=1, size=1, prob=0.5, ... )
y() # 0.5
y(log=TRUE) # -0.6931472
partial()
的伟大之处在于它可以自然地与%>%
管连接:
z <- partial(dbinom, size=1) %>% partial(prob=0.5) %>% partial(x=1)
z(log=TRUE) # -0.6931472
如果我正确理解你想做什么, 那么也许这效果更好:
f <- function(a_call) {
call_modify(call_standardise(call2(ensym(a_call)),
caller_env()),
x=1)
}
您可以带或不带字符使用:
f(print)
# print(x = 1)
f("print")
# print(x = 1)
eval(f(print))
# 1
或者更多间接:
a_call <- expr(print)
eval(call2(f, a_call))
# print(x = 1)
eval(expr(f(!!a_call)))
# print(x = 1)
由于我们在这里做了一些非标准评估, 事情变得有点棘手。call_standardise
需要能够找到您指定的函数, 而且很有可能会在调用f
的环境中找到它, 不一定在召唤call_standardise
的环境中, 在这种情况下,这将是f
的执行环境。 这就是为什么在调用call_standardise
时明确指定caller_env()
,即使这是后者env
的默认值, 因为默认参数是在函数的执行环境中计算的, 而显式参数是在调用方的环境中计算的。
下面是此问题的一个看起来很做作的示例:
f2 <- function(a_call) {
call_modify(call_standardise(call2(ensym(a_call))),
x=1)
}
e <- new.env()
e$foo <- function(x) { x + 1 }
with(e, f(foo))
# foo(x = 1)
with(e, f2(foo))
# Error in eval_bare(node_car(expr), env) : object 'foo' not found
但是,如果您要开发一个提供f
的包, 该示例不再人为:f
会存在于您的包的环境中, 其他包可以为仅在其各自命名空间中可用的函数调用它。
有关更多细节和描述, 检查此参考, 也许尝试为我的示例绘制调用树。
call2
通过将计算...
参数传递给可调用对象(第一个参数(来构造调用。例如,以下命令输出到控制台"y"
,因为计算传递给call2
的第二个参数,
> A <- call2(print, x=print('y'))
[1] "y"
并构造一个对print
的调用,该调用以x="y"
作为其参数(而不是x=print("y")
(:
> A
(function (x, ...)
UseMethod("print"))(x = "y")
为了绕过a_call
被评估然后在构造调用中传递(f
(,可以引用它,例如
f <- function(a_call) {
call_modify(a_call, x=1)
}
a_call <- call2(dbinom, size=1, prob=0.5)
y <- call2(f, quote(a_call))
现在:
> y
(function(a_call) {
call_modify(a_call, x=1)
})(a_call)