【发布时间】:2023-03-17 10:14:01
【问题描述】:
我在 R 中转发“...”时遇到了一些麻烦。
我找到了解决方案,但我仍然不明白为什么我的原始代码不正确。也许有人可以向我解释一下?
我准备了一个reprex:
# modify a string with glue.
# z is an optional argument
fun_A <- function(my_string, ..., z = NULL){
print(paste0("z value: ", as.character(z))) # do something with z here
print(list(...)) # to test: print ... to check that all variables are still there
my_string <- glue::glue(my_string, ...)
my_string
}
# when fun_A() is used inside fun_B, 'z' must be filled with the same value in fun_A() and fun_B().
fun_B <- function(z, my_string, ...){
my_string_mod <- rlang::enquo(my_string) %>%
rlang::call_modify(z = z) %>%
rlang::eval_tidy()
my_string_mod
# then other stuff, useless for the reprex
}
# calls fun_B() but for a specific string, now the argument of my_string are explicit.
fun_C_ok <- function(x, y){
fun_B(z = "i am z",
my_string = fun_A(my_string = "replace {x} and {y}.",
x = !!x, y = !!y)
)
一切如我所愿:
在 fun_A() 中,“z”按预期缺失。 'x' 和 'y' 已按预期更改
> fun_A(my_string = "replace {x} and {y}.", x = "this", y = "that")
[1] "z value: "
$x
[1] "this"
$y
[1] "that"
replace this and that.
在 fun_B() 中,'z' 在 fun_A() 中按预期进行了修改。 'x' 和 'y' 已按预期更改
> fun_B(z = "i am z", my_string = fun_A(my_string = "replace {x} and {y}.", x = "this", y = "that"))
[1] "z value: i am z"
$x
[1] "this"
$y
[1] "that"
replace this and that.
在 fun_C_ok() 中,'z' 在 fun_A() 中按预期进行了修改。 'x' 和 'y' 已按预期更改
> fun_C_ok(x = "this", y = "that")
[1] "z value: i am z"
$x
[1] "this"
$y
[1] "that"
replace this and that.
一开始,我这样写最后一个函数(没有bang-bang操作符(!!))
fun_C_notok <- function(x, y){
fun_B(z = "i am z",
my_string = fun_A(my_string = "replace {x} and {y}.",
x = x, y = y)
)
}
它不起作用,glue 在 fun_A() 中找不到“x”,但我不明白为什么,因为“x”和“y”存在于列表中(...)
> fun_C_notok(x = "this", y = "that")
[1] "z value: i am z"
$x
[1] "this"
$y
[1] "that"
Error in eval(parse(text = text, keep.source = FALSE), envir) :
object 'x' not found
11. eval(parse(text = text, keep.source = FALSE), envir)
10. eval(parse(text = text, keep.source = FALSE), envir)
9. .transformer(expr, env)
8. (function (expr)
{
eval_func <- .transformer(expr, env)
tryCatch(as.character(eval_func), error = function(e) { ...
7. glue_data(.x = NULL, ..., .sep = .sep, .envir = .envir, .open = .open,
.close = .close, .na = .na, .transformer = .transformer,
.trim = .trim)
6. glue::glue(my_string, ...)
5. fun_A(my_string = "replace {x} and {y}.", x = x, y = y, z = "i am z")
4. rlang::eval_tidy(.)
3. rlang::enquo(my_string) %>% rlang::call_modify(z = z) %>% rlang::eval_tidy()
2. fun_B(z = "i am z", my_string = fun_A(my_string = "replace {x} and {y}.",
x = x, y = y))
1. fun_C_notok(x = "this", y = "that")
有人明白为什么 glue() 在 fun_C_notok() 中找不到 'x' 吗??
【问题讨论】:
-
我认为这很可能是
glue::glue或其使用的功能之一中的错误。如果您查看该回溯,您会发现它正在做非常复杂的事情,并且他们可能做出了一个在您的示例中不成立的假设,例如传递给它的变量可以在调用者框架中进行评估,而不是在您的示例中其父级。 -
刚刚尝试了使用
rgl:::subst内部函数而不是glue::glue的示例,它工作正常。subst()需要字符串为"replace %x% and %y%.",但可以用作funA中的直接替换。 -
感谢您的回答。我已经在胶水 github 中询问了它是否是一个错误。