R中三点省略号的更新值

R中三点省略号的更新值,r,parameter-passing,ellipsis,rlang,R,Parameter Passing,Ellipsis,Rlang,我有一个函数foo() 我认为在这里使用某种通用的包装器(runtime\u gateway())并通过..向foo()传递参数是有意义的,因此我可以利用相同的“runtime gateway logic”处理具有不同参数集的任意函数 如果在while循环中运行foo(),我想更新它的一些参数,同时保留其他参数的默认值或传递值 我该怎么做 我了解rlang::dot_list(…)和朋友,并快速浏览了一下。看起来,其中任何一个都只允许从省略号内容中提取值或检查省略号内容,但我不知道如何“在传输过

我有一个函数
foo()

我认为在这里使用某种通用的包装器(
runtime\u gateway()
)并通过
..
foo()
传递参数是有意义的,因此我可以利用相同的“runtime gateway logic”处理具有不同参数集的任意函数

如果在while循环中运行
foo()
,我想更新它的一些参数,同时保留其他参数的默认值或传递值

我该怎么做

我了解
rlang::dot_list(…)
和朋友,并快速浏览了一下。看起来,其中任何一个都只允许从省略号内容中提取值或检查省略号内容,但我不知道如何“在传输过程中更新它”

雷普雷克斯 foo id_b:2020-02-21 14:10:22.906 #>身份证号码:2020-02-21 14:10:23.908 运行时网关(run_mode=“while”,at=lubridate::ymd_hms(“2020-02-21 10:30:00”)) #>“at”通过省略号传递: #> 2020-02-21 10:30:00 #>fun中的错误(at=at+60,…):形式参数“at”与多个实际参数匹配

由(v0.3.0)于2020-02-21创建,您可以通过添加
at
参数(如果不存在)来确保
dots
包含
at
参数,然后使用
dots
而不是
调用


runtime\u gateway在最后一行中,你为什么要尝试传递一个
at
参数,而它已经默认为
Sys.time()
?我的意思是,你通过传递
at=Sys.time()
给它一个固定的时间。为什么不将while循环中的
fun(at=Sys.time(),…)
更改为
fun(…)
,并且根本不传递
at
参数?@AllanCameron
at
Sys.time()
只是一些参数的示例,如果函数在
中运行而
loop@AllanCameron:我已经更新了我的问题,希望在
中更新
的部分,而
clear稍微更为惯用:
rlang::exec(fun,!!!dots)
而不是
do.call(…)
。另外,
rlang::list2()
rlang::dots\u list()
有一个更简单的API。很抱歉,我花了几天时间才回到这个问题上。感谢您的回答,并感谢@krlmlr将其放在
rlang
rails上。然而,通过切换到
do.call()
rlang::exec()
我基本上失去了传递
的“易用性”…
甚至更远的下游,对吗?在保留语法糖分的同时,
..
本质上是一个“语法糖化的美化arg列表”,难道没有办法改变它吗?@Rappster:使用
do.call()调用的函数的签名中仍然有省略号。我不知道有一种文档化的方法可以更新部分
foo <- function(
  id = "id_a",
  at = Sys.time()
) {
  message(stringr::str_glue("{id}: {at}"))
  Sys.sleep(1)
}

runtime_gateway <- function(
  fun = foo,
  run_mode = c("once", "while"),
  ... # Args to be passed to `fun`
) {
  run_mode <- match.arg(run_mode)

  if (run_mode == "once") {
    fun(...)
  } else if (run_mode == "while") {
    counter <- 0

    while(counter < 3) {
      # Goal: keep ellipsis value for `id` but *update* value for `at`
      dots <- rlang::dots_list(...)
      at <- if ("at" %in% names(dots)) {
        message("`at` was passed via ellipsis:")
        message(dots$at)
        dots$at
      } else {
        Sys.time()
      }

      fun(at = at + 60, ...)
      counter <- counter + 1
    }
  }
}

runtime_gateway()
#> id_a: 2020-02-21 14:09:16.779
runtime_gateway(at = lubridate::ymd_hms("2020-02-21 10:30:00"))
#> id_a: 2020-02-21 10:30:00

runtime_gateway(run_mode = "while")
#> id_a: 2020-02-21 14:10:18.897
#> id_a: 2020-02-21 14:10:19.900
#> id_a: 2020-02-21 14:10:20.902
runtime_gateway(run_mode = "while", id = "id_b")
#> id_b: 2020-02-21 14:10:21.905
#> id_b: 2020-02-21 14:10:22.906
#> id_b: 2020-02-21 14:10:23.908
runtime_gateway(run_mode = "while", at = lubridate::ymd_hms("2020-02-21 10:30:00"))
#> `at` was passed via ellipsis:
#> 2020-02-21 10:30:00
#> Error in fun(at = at + 60, ...): formal argument "at" matched by multiple actual arguments
runtime_gateway()
#> id_a: 2020-02-21 14:22:07

runtime_gateway(at = lubridate::ymd_hms("2020-02-21 10:30:00"))
#> id_a: 2020-02-21 10:30:00

runtime_gateway(run_mode = "while")
#> id_a: 2020-02-21 14:23:09
#> id_a: 2020-02-21 14:23:10
#> id_a: 2020-02-21 14:23:11

runtime_gateway(run_mode = "while", id = "id_b")
#> id_b: 2020-02-21 14:23:12
#> id_b: 2020-02-21 14:23:13
#> id_b: 2020-02-21 14:23:14

runtime_gateway(run_mode = "while", at = lubridate::ymd_hms("2020-02-21 10:30:00"))
#> `at` was passed via ellipsis:
#> 2020-02-21 10:30:00
#> id_a: 2020-02-21 10:31:00
#> `at` was passed via ellipsis:
#> 2020-02-21 10:30:00
#> id_a: 2020-02-21 10:31:00
#> `at` was passed via ellipsis:
#> 2020-02-21 10:30:00
#> id_a: 2020-02-21 10:31:00