r - 更新R中三点省略号的值

标签 r parameter-passing ellipsis rlang

我有一个函数 foo(),我希望能够以两种不同的“模式”调用它:一次或在 while 循环内调用。

我认为使用某种通用的包装器(runtime_gateway())并通过...将参数传递给foo()是有意义的在这里,我可以利用相同的“运行时网关逻辑”来实现具有不同参数集的任意函数。

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

我该怎么做?

我知道 rlang::dot_list(...) 和 friend ,并快速浏览了 https://github.com/r-lib/ellipsis 。似乎其中任何一个都只能从省略号内容中提取值或检查省略号内容,但我不知道如何“在传输过程中更新它”。

Reprex

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

reprex package于2020年2月21日创建(v0.3.0)

最佳答案

您可以通过添加 dots 参数(如果不存在)来确保它包含 at 参数,然后使用 分派(dispatch) fun而不是...do.call

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(...)
      if ("at" %in% names(dots)) {
        message("`at` was passed via ellipsis:")
        message(dots$at)
        dots$at <- dots$at + 60
      } else {
        dots$at <- Sys.time() + 60
      }

      do.call(fun, dots)
      counter <- counter + 1
    }
  }
}

这是输出:

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

reprex package于2020年2月21日创建(v0.3.0)

关于r - 更新R中三点省略号的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60338114/

相关文章:

r - 无法让 alpha 与 ggplot2::geom_sf 在 sf linestring 对象上一起使用

fortran - 在 Fortran 95 中按值传递参数

识别 R 中的日期时间格式

php - R 和 PHP 集成

python - Spyder-IDE 如何打开参数检查

jquery - chrome 中带省略号的多行文本问题

android - ellipsize=end 用省略号替换整个最后一行

postscript - 如何使用 postscript 在文本上换行或添加省略号?

R:是否有与 SAS 的 intck 函数等效的函数?

JavaScript - 在 onclick 函数中获取(this)参数的关联值