2

在一个包中,我想为 object 调用一个 S3 方法“compact” foobar

因此compact.foobar,我的包中将有一个函数以及compact函数本身:

compact = function(x, ...){
    UseMethod("compact", x)
}

但是,后者会与purrr::compact.

我可以默认使用purrrcompact.default = purrr::compact或可能 compact.list = purrr::compact)的方法,但如果用户没有purrr加载,那将毫无意义。

compact如何在用户环境中将我的方法默认为加载的 , 版本?(以便它使用purrr::compact、任何其他声明compact的函数,或丢失函数失败)

4

1 回答 1

1

不幸的是,S3 不能很好地处理这种情况。您必须手动搜索合适的功能。以下作品或多或少:

get_defined_function = function (name) {
    matches = getAnywhere(name)
    # Filter out invisible objects and duplicates
    objs = matches$objs[matches$visible & ! matches$dups]
    # Filter out non-function objects
    funs = objs[vapply(objs, is.function, logical(1L))]
    # Filter out function defined in own package.
    envs = lapply(funs, environment)
    funs = funs[! vapply(envs, identical, logical(1L), topenv())]
    funs[1L][[1L]] # Return `NULL` if no function exists.
}
compact.default = function (...) {
    # Maybe add error handling for functions not found.
    get_defined_function('compact')(...)
}

这用于查找R 知道getAnywhere的所有命名对象。compact然后它会过滤掉那些不可见的,因为它们不在附加的包中,以及那些重复的(这可能是多余的,但我们还是这样做了)。

接下来,它过滤掉任何不是函数的东西。最后它过滤掉compact我们自己的包定义的 S3 泛型。为此,它将每个函数的环境与包环境(由 给出topenv())进行比较。

这应该可行,但是如果在不同位置定义了多个具有相同名称的函数(它只是首先选择一个任意一个),它没有关于首选哪个函数的规则,并且它也不检查函数签名是否匹配(在 R 中这样做很难,因为函数调用和参数匹配非常灵活)。

于 2020-04-02T09:52:50.687 回答