r-基于长参数组合的调度S4方法



动机

我正在尝试创建一个通用的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, a, b) n + a + b
)
setMethod(
f = "genfunk",
signature = list(
a = "missing",
b = "missing",
c = "numeric",
d = "numeric"
),
definition = function(n, c, 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, a=1, c=2)                                                                        
Error in (function (classes, fdef, mtable)  : 
unable to find an inherited method for function ‘genfunk’ for signature ‘"numeric", "missing", "numeric", "missing"’

问题

  1. 是否可以创建一个";异常";签名来处理所有这些不正确的参数不匹配
  2. 是否可以重命名有效签名,以便在文档中正确标记它们?在我的实际案例中,genfunk的文档包含以下内容:
## S4 method for signature 
## 'numeric,numeric,missing,missing'
genfunk(n, a, b)
## S4 method for signature 
## 'missing,missing,numeric,numeric'
genfunk(n, c, d)

这对用户来说毫无意义,除非他们查看泛型的代码。我实际代码中的情况更糟,因为签名列表目前包含来自十几个不同方法(和计数)的近20多个参数。

我认为这个技巧应该在文档中的某个地方,但我觉得我已经没有什么东西可以尝试了。目前,通用记录为:

#' @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, a=1, c=2) 
#> Error: Weird combination of arguments

由reprex包于2021-02-03创建(v0.3.0)

最新更新