我希望能够找到函数.Deprecated
是否在某个函数中使用,比如my.fun
。举个例子:
my.fun <- function (...) {
.Deprecated("my_fun")
my_fun(...)
}
目前我正在使用
grepl(".Deprecated", as.character(body(getFromNamespace("my.fun", "mypackage"))))
哪个工作正常,在上面的例子中它返回
[1] FALSE TRUE FALSE
但是如果我在一个函数中使用单词.Deprecated
作为一个简单的字符串,那么它也会被拾取。我知道mvbutils::foodweb()
和mvbutils::calleer.of()
函数,但只有在我明确定义自己的.Deprecated
函数时它们才有效。有人知道一种优雅的方法来搜索一个函数,而不是一个字符串吗?
答案 0 :(得分:2)
健壮的解决方案必须检查函数体的语法,而不是进行字符串搜索。幸运的是,R使这相对容易:
variables = all.names(body(myfunction))
'.Deprecated' %in% variables
有一点需要注意,这不会测试.Deprecated
是否实际引用base::.Deprecated
; 任何使用该符号作为变量/函数名称将显示在上面。但是,在没有实际执行函数的情况下,找出符号所引用的函数是不可能的,所以这样做就好了,不执行所有函数并跟踪它们的函数调用。
您可以做的最好的事情是获取函数中使用的名称列表,并在定义函数的上下文中获取它们的定义。这可以看作是 okay 启发式:如果你的函数使用.Deprecated
,并且该符号是在定义函数的上下文中定义的,那么这将产生正确的定义。但是,它会在以下情况下失败:
误报:
f1 = function () {
.Deprecated = 42
}
假阴性:
f2 = function () {
x = get('.Deprecated', mode = 'function')
x("f1")
}
因此请谨慎使用。
calls_function = function (f, target, target_name = deparse(substitute(target_name))) {
find_definition = function (candidates)
mget(candidates, environment(target), mode = 'function')
resolves_to_target = function (candidates)
sapply(find_definition(candidates), identical, target)
variables = unique(all.names(body(f)))
candidates = grep(target_name, variables, fixed = TRUE)
length(candidates) > 0 && any(resolves_to_target(variables[candidates]))
}
用法:
calls_function(f1, .Deprecated)
请注意,函数名称作为不带引号的参数传递;如果你想传递base::.Deprecated
,你还需要提供“不合格”的名字作为第三个参数:
calls_function(f1, base::.Deprecated, '.Deprecated')