假设我们在R
包中有这个功能。
prova <- function() {
print(attr(prova, 'myattr'))
print(myattr(prova))
invisible(TRUE)
}
'myattr<-' <- function(x, value) {
attr(x, 'myattr') <- value
x
}
myattr <- function(x) attr(x, 'myattr')
所以,我安装包然后测试它。这是结果:
prova()
# NULL
# NULL
myattr(prova) <- 'ciao' # setting 'ciao' for 'myattr' attribute
prova()
# NULL
# NULL # Why NULL here ?
myattr(prova)
# [1] "ciao"
attr(prova, 'myattr')
# [1] "ciao"
问题是:如何从内部获取函数的属性?
在函数本身内部,我无法获得其属性,如示例所示。
我认为解决方案将是系列语言&#34;计算语言&#34; (match.call()[[1L]]
,substitute
,环境和朋友)。我错了吗?
我认为这里的重点是这个函数在一个包中(因此,它有环境和命名空间),我需要它自己的属性,在包裹中,而不是在外面。
答案 0 :(得分:0)
您可以将get
与envir
参数一起使用。
prova <- function() {
print(attr(get("prova", envir=envir.prova), 'myattr'))
print(myattr(prova))
invisible(TRUE)
}
例如:
envir.prova <- environment()
prova()
# NULL
# NULL
myattr(prova) <- 'ciao'
prova()
# [1] "ciao"
# [1] "ciao"
其中envir.prova
是一个变量,其值设置为定义prova
的环境。
或者,您可以使用get(.. envir=parent.frame())
,但这不太可靠,因为您必须跟踪调用,并确保在目标环境和调用环境之间使用相同名称的另一个对象。
关于使用parent.frame()
与使用明确的环境名称:parent.frame
,顾名思义,“向上一级”。通常,这正是你想去的地方,所以工作正常。然而,即使您的目标是在更高的环境中获取对象,R
也会搜索调用堆栈,直到找到具有匹配名称的对象。很多时候,parent.frame()
就好了。
HOWEVER 如果您在调用parent.frame()
的位置与对象位于其中一个中间环境中 AND 之间存在多个调用,则存在另一个对象如果名称相同,则R
将停在该中间环境并返回其对象,该对象不您要查找的对象。
因此,parent.frame()
有一个参数n
(默认为1),因此您可以告诉R
开始在n
级别搜索。
这是我所指的“保持跟踪”,开发人员必须注意其间的呼叫次数。解决这个问题的直接方法是在调用相关函数的每个函数中都有一个n
参数,并将该值默认为1.然后对于envir
参数,使用:{ {1}} get/assign/eval/etc
然后,如果您从(.. , envir=parent.frame(n=n) )
致电Func2
,(Func1
和Func1
都有Func2
参数),n
正在呼叫Func2
,您使用:
prova
正如你所看到的,它不是复杂的,但它是*乏味的*有时看起来像一个bug爬进去,这只是忘记携带n。
因此,我更喜欢使用带有环境名称的固定变量。
答案 1 :(得分:-1)
我找到的解决方案是:
myattr <- function(x) attr(x, 'myattr')
'myattr<-' <- function(x, value) {
# check that x is a function (e.g. the prova function)
# checks on value (e.g. also value is a function with a given precise signature)
attr(x, 'myattr') <- value
x
}
prova <- function(..., env = parent.frame()) {
# get the current function object (in its environment)
this <- eval(match.call()[[1L]], env)
# print(eval(as.call(c(myattr, this)), env)) # alternative
print(myattr(this))
# print(attr(this, 'myattr')
invisible(TRUE)
}
我要感谢@RicardoSaporta提供有关跟踪电话跟踪的帮助和说明。
此解决方案在例如myattr(prova) <- function() TRUE
嵌套在func1
中prova
,而func2
调用func1
(env
调用prova
。除非您没有正确更新其参数prova <- function(..., pos = 1L) {
# get the current function object (in its environment)
this <- eval(match.call()[[1L]], parent.frame(n = pos)
print(myattr(this))
# ...
}
...
为了完整性,按照@RicardoSaporta的建议,我略微修改了pos
函数:
prova
这样,如果传入了正确的myfun1 <- function() {
myattr(prova) <- function() print(FALSE)
myfun2(n = 2)
}
myfun2 <- function(n) {
prova(pos = n)
}
myfun1()
# function() print(FALSE)
# <environment: 0x22e8208>
参数,它也可以在嵌套时使用。
通过此修改,您可以更轻松地在功能{{1}}上设置属性的环境中消失。
{{1}}