r - 修改函数参数中的调用
问题描述
函数如何检查和修改作为参数接收的调用的参数?
应用程序:用户将函数调用a
作为参数提供给函数b
,但他们忘记指定所需的参数之一a
。功能如何b
检测并解决问题?
在这个最小的例子中,函数a
需要两个参数:
a <- function(arg1, arg2) {
return(arg1 + arg2)
}
函数b
接受一个调用和一个参数。注释行表明我需要做什么:
b <- function(CALL, arg3) {
# 1. check if `arg2` is missing from CALL
# 2. if `arg2` is missing, plug `arg3` in its place
# 3. return evaluated call
CALL
}
预期行为:
b(CALL = a(arg1 = 1, arg2 = 2), arg3 = 3)
> 3
b(CALL = a(arg1 = 1), arg3 = 3)
> 4
由于用户忘记指定所需的arg2
参数,第二次调用当前失败。函数如何b
自动修复这个错误?
我可以利用惰性评估在a
评估之前修改调用吗?我看了看,rlang::modify_call
但无法弄清楚。
解决方案
这是一种可行的方法
b <- function(CALL, arg3) {
scall <- substitute(CALL)
stopifnot(is.call(scall)) #check that it's a call
lcall <- as.list(scall)
if (!"arg2" %in% names(lcall)) {
lcall <- c(lcall, list(arg2 = arg3))
}
eval.parent(as.call(lcall))
}
我们使用substitute()
CALL 参数来获取未评估的版本。我们将其转换为列表,以便我们可以修改它。然后我们将另一个带有我们想要的参数名称/值的列表附加到列表中。最后,我们将列表重新转换为调用,然后在调用者的环境中而不是在函数体本身中评估该调用。
如果您想使用rlang::modify_call
其他rlang
功能,您可以使用
b <- function(CALL, arg3) {
scall <- rlang::enquo(CALL)
stopifnot(rlang::quo_is_call(scall))
if (!"arg2" %in% names(rlang::quo_get_expr(scall))) {
scall <- rlang::call_modify(scall, arg2=arg3)
}
rlang::eval_tidy(scall, env = rlang::caller_env())
}
推荐阅读
- java - SLF4J/Java 日志记录:是否可以自动添加日志参数?
- linux - 使用管道时Grep没有给出预期的结果
- python - 访问外部信息后,Python Telegram bot 无法与多个用户合作
- bash - 嵌套 for 循环 shell 脚本
- google-cloud-platform - 谷歌云平台和 API:支付
- c# - HttpWebRequest.Headers 缺少一些标头
- c++ - 使用 nlohmann 访问 JSON 的数组元素“[]”
- android - 错误:无法找到或加载主类 \AppData\Local\Android\Sdk\cmdline-tools\latest\bin\\
- sql - 如何解决唯一约束错误?
- php - WordPress:获取带有 ID 的帖子标题