如何将 S3 方法声明为默认加载环境?
How to declare S3 method to default to loaded environment?
在包中,我想为对象 foobar
.
调用 S3 方法 "compact"
因此我的包中会有一个 compact.foobar
函数,以及 compact
函数本身:
compact = function(x, ...){
UseMethod("compact", x)
}
但是,后者会与 purrr::compact
冲突。
我可以默认方法使用 purrr
(compact.default = purrr::compact
,或者
compact.list = purrr::compact
),但如果用户没有加载 purrr
,那将毫无意义。
如何在用户环境中将我的方法默认为 compact
的加载版本? (因此它使用 purrr::compact
、任何其他声明的 compact
函数,或因缺少函数而失败)
遗憾的是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')(...)
}
这使用 getAnywhere
查找 R 知道的所有名为 compact
的对象。然后过滤掉那些不可见的,因为它们不在附加包中,以及那些重复的(这可能是多余的,但我们还是这样做了)。
接下来,它过滤掉所有不是函数的东西。最后它过滤掉我们自己的包定义的 compact
S3 泛型。为此,它将每个函数的环境与包环境(由 topenv()
给出)进行比较。
这应该可行,但如果在不同位置定义了多个具有相同名称的函数(它只是先选择一个任意函数),它没有关于优先选择哪个函数的规则,并且它也不会检查是否函数签名匹配(在 R 中很难做到这一点,因为函数调用和参数匹配非常灵活)。
在包中,我想为对象 foobar
.
因此我的包中会有一个 compact.foobar
函数,以及 compact
函数本身:
compact = function(x, ...){
UseMethod("compact", x)
}
但是,后者会与 purrr::compact
冲突。
我可以默认方法使用 purrr
(compact.default = purrr::compact
,或者
compact.list = purrr::compact
),但如果用户没有加载 purrr
,那将毫无意义。
如何在用户环境中将我的方法默认为 compact
的加载版本? (因此它使用 purrr::compact
、任何其他声明的 compact
函数,或因缺少函数而失败)
遗憾的是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')(...)
}
这使用 getAnywhere
查找 R 知道的所有名为 compact
的对象。然后过滤掉那些不可见的,因为它们不在附加包中,以及那些重复的(这可能是多余的,但我们还是这样做了)。
接下来,它过滤掉所有不是函数的东西。最后它过滤掉我们自己的包定义的 compact
S3 泛型。为此,它将每个函数的环境与包环境(由 topenv()
给出)进行比较。
这应该可行,但如果在不同位置定义了多个具有相同名称的函数(它只是先选择一个任意函数),它没有关于优先选择哪个函数的规则,并且它也不会检查是否函数签名匹配(在 R 中很难做到这一点,因为函数调用和参数匹配非常灵活)。