依赖其他参数的匹配参数最佳实践

4

我是 R 函数的新手,到目前为止,我会检查参数,例如:

foo = function(state = c("solid", "liquid"),
               thing = c("rock", "water")) {
  
  state = match.arg(state)
  thing = match.arg(thing)
  
  if (state == "solid" & thing == "water") {
    stop("thing can't be water if state is solid!")
  }
  
  if (state == "liquid" & thing == "rock") {
    stop("thing can't be rock if state is liquid!")
  }
  
}

foo("solid", "brick")
#> Error in match.arg(thing): 'arg' deve ser um dentre "rock", "water"

foo("solid", "water")
#> Error in foo("solid", "water"): thing can't be water if state is solid!

foo("liquid", "rock")
#> Error in foo("liquid", "rock"): thing can't be rock if state is liquid!

使用reprex包(v0.3.0)于2020-06-28创建

但是当处理多个参数时,似乎需要付出很多工作。

我查看了assetthatcheckmate包,但对于正确或标准的做法并不清楚。

1个回答

4

我建议使用“允许列表”(allowlist)或“拒绝列表”(denylist),取决于哪个更短(你将有多少例外情况),但你必须以某种方式硬编码它们。

例如:

foo = function(state = c("solid", "liquid", "both"),
               thing = c("rock", "brick", "water", "either")) {
  
  state = match.arg(state)
  thing = match.arg(thing)

  state_denylist <- list(
    solid = "water",
    liquid = c("rock", "brick")
  )

  if (thing %in% state_denylist[[state]]) {
    stop("thing cannot be ", sQuote(thing), " if state is ", sQuote(state))
  }
 
}

或者,如果定义允许组合更容易,则可以使用state_allowlist并相应地更改您的逻辑(... && ! thing %in% ...)。


AlbersonMiranda,我稍微简化了一下,因为如果“state”不在拒绝列表中,则“%in% state_denylist [[state]]”实际上是“%in% NULL”,这始终(并且安全地)为“FALSE”。以前的版本有点更声明性,但可能主要是风格问题。由你决定。 - r2evans

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接