如何编写一个也接受字符输入的 NES 函数?
How to write an NES function that also takes character input?
我正在开发一个将字符串作为函数参数的 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 功能)。
有什么想法吗?
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))
}
我正在开发一个将字符串作为函数参数的 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 功能)。
有什么想法吗?
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))
}