基于参数的长组合调度 S4 方法
Dispatching S4 methods based on long combination of arguments
动机
我正在尝试创建一个通用的 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"’
问题
- 是否可以创建一个“异常”签名来处理所有这些不正确的参数不匹配?
- 是否可以重命名有效签名以便在文档中正确标记它们?在我的真实案例中,
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)
这对用户来说毫无意义,除非他们查看泛型的代码。我的实际代码中的情况更糟,因为签名列表当前包含来自十几种不同方法(并且还在增加)的近两打参数。
我认为技巧应该在文档中的某处,但我觉得我 运行 没有什么可以尝试的了。目前,泛型记录为:
#' @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 package (v0.3.0)
创建于 2021-02-03
动机
我正在尝试创建一个通用的 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"’
问题
- 是否可以创建一个“异常”签名来处理所有这些不正确的参数不匹配?
- 是否可以重命名有效签名以便在文档中正确标记它们?在我的真实案例中,
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)
这对用户来说毫无意义,除非他们查看泛型的代码。我的实际代码中的情况更糟,因为签名列表当前包含来自十几种不同方法(并且还在增加)的近两打参数。
我认为技巧应该在文档中的某处,但我觉得我 运行 没有什么可以尝试的了。目前,泛型记录为:
#' @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 package (v0.3.0)
创建于 2021-02-03