Обновление значений трехточечного многоточия в R - PullRequest
2 голосов
/ 21 февраля 2020

У меня есть функция foo(), которую я бы хотел вызывать в двух разных «режимах»: один раз или через некоторое время. L oop.

Я подумал, используя несколько обобщенно c wrapper (runtime_gateway()) и передача аргументов через ... в foo() будет иметь здесь смысл, чтобы я мог использовать один и тот же «logi gateway logi c» для произвольных функций с разными наборами аргументов.

Если запустить foo() в течение некоторого времени l oop, я бы хотел обновить некоторые своих аргументов, в то время как сохраняя значения по умолчанию или передаваемые значения других аргументов.

Как бы я это сделал?

Я знаю rlang::dot_list(...) и друзей и быстро взглянул на https://github.com/r-lib/ellipsis. Кажется, что любой из них позволил бы только собирать значения или проверять содержимое многоточия, но я не вижу, как я мог бы «обновить его при передаче».

Представляет

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

Создано в 2020-02-21 пакетом Представить (v0.3.0)

1 Ответ

2 голосов
/ 21 февраля 2020

Вы можете убедиться, что dots содержит аргумент at, добавив его, если он отсутствует, а затем отправить fun, используя dots вместо ... с 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

Создано в 2020-02-21 с помощью пакета Представить (v0.3.0)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...