问题描述
动机
我正在尝试创建一个通用 R 函数,该函数不根据主参数 (n
) 的签名,而是根据辅助参数的存在来调度方法。
我不确定这在 S3 中是否可行,但我知道如何在 S4 中做到这一点(尽管以草率的方式,您可能会注意到)。不知道 R5 或 S6。
MRE
setGeneric(
name = "genfunk",def = function(n,a,b,c,d) standardGeneric("genfunk"),signature = c("a","b","c","d")
)
setMethod(
f = "genfunk",signature = list(
a = "numeric",b = "numeric",c = "missing",d = "missing"
),deFinition = function(n,b) n + a + b
)
setMethod(
f = "genfunk",signature = list(
a = "missing",b = "missing",c = "numeric",d = "numeric"
),d) n * c * d
)
r$> genfunk(10,a=1,b=2)
[1] 13
r$> genfunk(10,c=3,d=2)
[1] 60
问题
r$> genfunk(10,c=2)
Error in (function (classes,fdef,mtable) :
unable to find an inherited method for function ‘genfunk’ for signature ‘"numeric","missing","numeric","missing"’
问题
## S4 method for signature
## 'numeric,numeric,missing,missing'
genfunk(n,b)
## S4 method for signature
## 'missing,numeric'
genfunk(n,d)
这对用户没有意义,除非他们查看通用代码。我的实际代码中的情况更糟,因为签名列表目前包含来自十几种不同方法(和计数)的近两打参数。
我认为这个技巧应该在文档的某个地方,但我觉得我已经没有什么可以尝试的了。目前,泛型被记录为:
#' @title Yes,title!
#' @param n Enn
#' @export
并且每个方法都记录为:
#' @title AB funk
#' @param a Ehi!
#' @param b Bee
#' @rdname genfunk
解决方法
抱歉,这不是 S4,但从您提出问题的方式来看,我相信您可能也对可能的 S3 解决方案感到好奇。如果我理解正确,您希望根据命名参数的某些组合的存在来调度方法。我认为没有办法为您想要允许的每个组合手动定义方法,然后为其余的组合创建一个“默认方法”。基于 S3 中的参数进行调度的一种方法是:
genfunk <- function(x,...){
newclass <- paste(names(list(...)),collapse = "_")
class(x) <- c(newclass,class(x))
genfunkInt(x,...)
}
genfunkInt <- function(x,...){
UseMethod("genfunkInt",x)
}
genfunkInt.a_b <- function(...) {
Reduce(`+`,list(...))
}
genfunkInt.c_d <- function(...) {
Reduce(`*`,list(...))
}
genfunkInt.default <- function(x,...) {
stop("Weird combination of arguments",call. = FALSE)
}
genfunk(10,a=1,b=2)
#> [1] 13
#> attr(,"class")
#> [1] "a_b" "numeric"
genfunk(10,c=3,d=2)
#> [1] 60
#> attr(,"class")
#> [1] "c_d" "numeric"
genfunk(10,c=2)
#> Error: Weird combination of arguments
由 reprex package (v0.3.0) 于 2021 年 2 月 3 日创建