【问题标题】:How to write an NES function that also takes character input?如何编写一个也接受字符输入的 NES 函数?
【发布时间】:2015-10-19 12:22:17
【问题描述】:

我正在开发一个将字符串作为函数参数的 R 包。现在我想使用非标准评估来允许非字符串输入。另外,为了保持向后兼容性,我想保留函数接受字符串的可能性。

Hadley 给出了一个带有子集函数的example,并建议每个 NES 函数都应该伴随一个标准的评估函数。

library(lazyeval)
# standard evaluation
subset2_ <- function(df, condition) {
    r <- lazy_eval(condition, df)
    r <- r & !is.na(r)
    df[r, , drop = FALSE]
} 

subset2_(mtcars, lazy(mpg > 31))


# NES can be written easily afterwards

subset2 <- function(df, condition) {
    subset2_(df, lazy(condition))
}

虽然 SE 函数现在也接受带引号的输入,

subset2_(mtcars, "mpg > 31")

NSE 函数抛出错误:

subset2(mtcars, "mpg > 31")

但我希望用户对带引号和不带引号的参数都有相同的函数(NSE 函数)。

有什么想法吗?

【问题讨论】:

  • 我会添加另一个参数来区分这两种情况。即 with=FALSE 用于字符大小写 à la data.table 方式。

标签: r eval lazy-evaluation


【解决方案1】:

NSE 函数接受 NSE 输入。这就是这种模式的重点,不是吗?

subset2(mtcars, mpg > 31)

当然,您也可以允许 NSE 函数接受字符输入,但我强烈建议您不要这样做。不要混合 SE 和 NSE,没有任何优势,而且会造成混乱(还有潜在的错误,因为您正在混合域)。

也就是说,以下当然有效:

subset2 <- function(df, condition) {
    if (is.character(substitute(condition)))
        subset2_(df, condition)
    else
        subset2_(df, lazy(condition))
}

如果您出于向后兼容性的原因希望在同一功能中允许 NSE 和 SE,我建议在未来版本中逐步淘汰 SE 版本,并暂时添加弃用警告。添加弃用警告:

subset2 <- function(df, condition) {
    if (is.character(substitute(condition))) {
        msg = sprintf(paste0('Calling %s with a quoted expression is',
                             ' deprecated. Pass an unquoted expression',
                             ' instead, or use %s.'),
                      sQuote('subset2'), sQuote('subset2_'))
        .Deprecated(msg = msg)
        subset2_(df, condition)
    }
    else
        subset2_(df, lazy(condition))
}

【讨论】:

  • 感谢您。那么您建议如何过渡到 NSE 并保持向后兼容性?
  • @Marti Ah,向后兼容是一个很好的论据。对此的标准解决方案是发布一个主要修订版,其中旧行为已被弃用。在那之后的下一个主要版本中,旧的行为被删除,破坏了向后兼容性。
  • 我认为这就是要走的路。如果我在未引用的表达式上使用 is.character ,则会引发错误。 Error in subset2(mtcars, mpg &gt; 31) : object 'mpg' not found
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-12-05
  • 2016-10-06
  • 1970-01-01
  • 2018-06-17
  • 2014-02-25
  • 2022-11-15
  • 1970-01-01
相关资源
最近更新 更多