【问题标题】:Dispatching S4 methods based on long combination of arguments基于参数的长组合调度 S4 方法
【发布时间】:2021-02-03 09:50:04
【问题描述】:

动机

我正在尝试创建一个通用 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)

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

我认为诀窍应该在文档中的某个地方,但我觉得我已经没有东西可以尝试了。目前,泛型被记录为:

#' @title Yes, title!
#' @param n Enn
#' @export

每种方法都记录为:

#' @title AB funk
#' @param a Ehi!
#' @param b Bee
#' @rdname genfunk

【问题讨论】:

  • 所以,简而言之,您想为每个参数组合提供方法吗?
  • @tjebo,差不多。我想为一些(互斥的)参数组合提供方法,并且可能为其余的参数组合提供一个保护伞(只是为了向用户提供一些关于如何使用泛型的有用反馈)。
  • 您查看过dotsMethods 的帮助页面吗?您的函数可以使用 ... 作为参数来代替命名参数吗?
  • @JDL,感谢您指出这一点,我不知道有一个文档页面。如果我取得进展,我会试一试并回到这里。

标签: r generics methods s4


【解决方案1】:

抱歉,这不是 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 年 2 月 3 日创建

【讨论】:

  • 感谢您的贡献!我真的不在乎我最终使用哪个对象系统。您在泛型中定义类的想法听起来很有希望,我会试一试。
猜你喜欢
  • 2020-02-29
  • 1970-01-01
  • 2013-04-29
  • 2015-01-13
  • 2022-11-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多