我正在維護一個以單個函式為中心的包,其中包含一些強制引數以及許多可選引數。
隨著我的函式的成熟,可選引數的順序也在變化,因此按順序呼叫它們會導致破壞性變化。
如果這些后面的引數是按位置而不是按名稱呼叫的,我想拋出警告/錯誤(不確定什么是最好的)。
這是一些具有預期輸出的偽代碼:
crosstable = function(data, cols=NULL, ..., by=NULL, opt1=FALSE, opt2=FALSE, opt3=FALSE){
warn_if_unnamed(by)
stop_if_unnamed(opt1)
stop_if_unnamed(opt2)
stop_if_unnamed(opt3)
doStuff(data, cols, by, opt1, opt2, opt3)
}
crosstable(mtcars, c(cyl, am), by=vs, opt3=TRUE) #OK
crosstable(mtcars, c(cyl, am), by=vs, TRUE) #error as `opt1` might become `opt56` in the future
crosstable(mtcars, c(cyl, am), vs, opt2=TRUE) #warning (?) as `by` will not move but it would be clearer
我怎樣才能做到這一點?
編輯:
感謝 @user2554330 和其他一些 SO 帖子(這里),我終于讓它作業了,盡管如果與管道一起使用它將無法作業:
warn_if_unnamed <- function(argname){
.call = sys.call(-1)
f = get(as.character(.call[[1]]), mode="function", sys.frame(-2))
mc = names(as.list(match.call(definition=f, call=.call))) #https://stackoverflow.com/a/17257053/3888000
sc = names(as.list(.call))
if(argname %in% mc && !argname %in% sc){
warning(argname," is referenced by position, not name")
}
}
myfun = function(x, y=NULL, opt1=FALSE, opt2=FALSE, opt3=FALSE){
warn_if_unnamed("opt1")
warn_if_unnamed("opt2")
warn_if_unnamed("opt3")
invisible()
}
myfun(1, 2)
myfun(1, 2, T, opt2=1)
#> Warning in warn_if_unnamed("opt1"): opt1 is referenced by position, not name
myfun(1, 2, opt1=T, 1, opt3)
#> Warning in warn_if_unnamed("opt2"): opt2 is referenced by position, not name
#> Warning in warn_if_unnamed("opt3"): opt3 is referenced by position, not name
myfun(1, 2, opt2=T, 1, opt3)
#> Warning in warn_if_unnamed("opt1"): opt1 is referenced by position, not name
#> Warning in warn_if_unnamed("opt1"): opt3 is referenced by position, not name
由reprex 包(v2.0.1)于 2021 年 10 月 20 日創建
不過,我可能會進行一些重構以將警告收集到一個單一的警告中。
PS:最后一行看起來像是reprex().
uj5u.com熱心網友回復:
您可以使用該sys.call()函式來查看您的函式是如何被呼叫的,以及match.call()R 如何將引數與引數匹配。所以代碼
warn_if_unnamed(by)是:
if ("by" %in% names(as.list(match.call())) &&
!"by" %in% names(as.list(sys.call())))
warning("'by' should be named")
可以把它放在一個函式中;您需要使用where引數 tosys.call()并match.call()查看函式呼叫者的引數,而不是其warn_if_unnamed自身的引數。
uj5u.com熱心網友回復:
這可能是一個warn_if_unnamed函式:
warn_if_unnamed <- function(argname){
arguments <- as.list(sys.call(which = -1)) # get arguments of sys.call
arg_name <- deparse(substitute(argname))# get variable name
arg_named <- arg_name %in% names(arguments)
if(!arg_named){
warning(arg_name," is referenced by position, not name")
}
}
使用示例:
myfun <- function( arg1,arg2=2,arg3=3 ) {
warn_if_unnamed(arg2)
}
myfun(1,2)
#In warn_if_unnamed(arg2) : arg2 is referenced by position, not name
如果未命名的錯誤可能類似于error()而不是warning()
uj5u.com熱心網友回復:
func <- function(data, cols = NULL, ...) {
opt_args <- list(...)
if(length(opt_args) > 0 && is.null(names(opt_args))) {
stop("Optional arguments must be named")
}
allowed_args <- c("opt1", "opt2")
if(length(setdiff(names(opt_args), allowed_args)) > 0) {
warning("Additional unknown arguments are ignored")
}
opt_args
}
# ok
func(iris, c("Sepal.Length", "Sepal.Width"))
#> list()
func(iris, c("Sepal.Length", "Sepal.Width"), opt1 = "foo")
#> $opt1
#> [1] "foo"
# warning
func(iris, c("Sepal.Length", "Sepal.Width"), opt3 = "foo")
#> Warning in func(iris, c("Sepal.Length", "Sepal.Width"), opt3 = "foo"):
#> Additional unknown arguments are ignored
#> $opt3
#> [1] "foo"
# error
func(iris, c("Sepal.Length", "Sepal.Width"), "foo")
#> Error in func(iris, c("Sepal.Length", "Sepal.Width"), "foo"): Optional arguments must be named
由reprex 包(v2.0.1)于 2021 年 10 月 20 日創建
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/327693.html
上一篇:繪制R中因子的時間序列資料串列
