【问题标题】:Evaluate elipsis (dots) multiple times, substitute arguments多次评估省略号(点),替换参数
【发布时间】:2016-04-28 12:37:51
【问题描述】:

上下文

我在 R 中使用包装函数调用的“省略号”或“点”

main_function <- function(...)

如果我想评估一次,我会这样做

main_function <- function(...) {
    res = list(...)}

效果很好

问题

fun_A <- function(arg_A){
    print(paste("I am A", paste0(round(runif(arg_A, 0,1), 2),collapse = ", ")))
}

fun_B <- function(arg_B){
    print(paste("I am B", paste0(round(runif(arg_B, 1,2), 2),collapse = ", ")))
}

这里的结果被评估一次并复制 3 次:

main_fun_wrong <- function(..., times) {
    res = list(...)
    replicate(times, eval(res))
}

main_fun_wrong(fun_A(1), fun_B(2), times = 3)

在这里有效:

main_fun <- function(..., times) {
    calls = match.call(expand.dots = FALSE)$`...`
    replicate(times, lapply(1:length(calls), function(num) eval(calls[[num]])), simplify = F)
}

main_fun(fun_A(1),fun_B(2), times = 3)

但是现在如果 arg_A 是一个对象而不是一个值,它将无法在环境中找到 arg_A 和 arg_B。

main_fun_problem <- function(arg_A, arg_B) {
    main_fun(fun_A(arg_A),fun_B(arg_B), times = 3)
}

main_fun_problem(1,2)

我遇到了一个错误:

fun_A(arg_A) 中的错误:找不到对象“arg_A”

我不知道 R 在第一个示例中第一次找到 list(...) 时会做什么,但我只想重复多次。

【问题讨论】:

  • 你能提供一个更具体的例子吗?
  • @nrussell Thx.I 没有提供示例,但改写它以使其更清晰
  • replicate(10, eval(calls)) 不会评估 10 次,它只是复制单次评估结果的 10 倍
  • @jangorecki 确实,但如果我将它包装在 for 循环中,问题仍然存在
  • 您也可以阅读microbenchmark::microbenchmark 函数的源代码,因为它完全符合您的要求

标签: r functional-programming ellipsis


【解决方案1】:

这是我的解决方案,任何替代方案都可以。

事情是在我们调用函数的那一刻用它的值替换变量。

main_fun_solution <- function(arg_A, arg_B) {
    eval(substitute(main_fun(fun_A(arg_A),fun_B(arg_B), times = 3), list("arg_A" =  arg_A, "arg_B" =  arg_B)))
}

main_fun_solution(1,2)

NB: list("arg_A" = arg_A, "arg_B" = arg_B)` 让我心血来潮(其实是整体解决方案)

【讨论】:

  • 刚刚遇到this。我会进一步阅读,它看起来是一个不错的选择。
猜你喜欢
  • 1970-01-01
  • 2012-01-22
  • 2012-11-01
  • 2019-05-27
  • 1970-01-01
  • 1970-01-01
  • 2014-04-13
  • 2022-07-07
相关资源
最近更新 更多