2

假设我们在一个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"

问题是:如何从自身内部获取函数的属性?

如示例所示,在函数本身内部,我无法获取其属性。

我想解决方案将是“语言计算”系列(match.call()[[1L]], substitute, 环境和朋友)。我错了吗?

我认为这里重要的一点是这个函数在一个包中(所以,它有它的环境和命名空间),我需要它的属性在自身内部,在包中,而不是在外部。

4

2 回答 2

0

您可以getenvir参数一起使用。

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" 

Whereenvir.prova是一个变量,您将其值设置prova为定义的环境。
或者,您可以使用get(.. envir=parent.frame()),但这不太可靠,因为您还必须跟踪调用,并确保目标环境和调用环境之间存在另一个具有相同名称的对象。

关于评论中问题的更新:

关于使用parent.frame()与使用显式环境名称: parent.frame顾名思义,“上一层楼”。通常,这正是您想去的地方,所以效果很好。然而,即使您的目标是在更高的环境中获取对象,也要向上R搜索调用堆栈,直到找到具有匹配名称的对象。所以很多时候,parent.frame()就好了。

但是parent.frame(),如果在您调用的位置和对象所在的位置之间有多个调用,并且在其中一个中间环境中存在另一个具有相同名称的对象,那么R将在该中间环境停止并返回对象,这不是对象你在找。

因此,parent.frame()有一个参数n(默认为 1),以便您可以告诉它从后面的级别R开始搜索。n

这就是我所说的“跟踪”,开发人员必须注意两者之间的调用次数。解决此问题的直接方法是n在调用相关函数的每个函数中都有一个参数,并将该值默认为 1。然后对于envir参数,您使用:get/assign/eval/etc (.. , envir=parent.frame(n=n) )

然后,如果您Func2Func1, (两者都有一个参数)调用并且Func1正在调用,则使用:Func2nFunc2prova

  Func1 <- function(x, y, ..., n=1) { 

    ... some stuff ... 
    Func2( <some, parameters, etc,> n=n+1)
  }  


  Func2 <- function(a, b, c, ..., n=1) { 

     .... some stuff.... 
     eval(quote(prova()), envir=parent.frame(n=n) )
  }

正如你所看到的,它并不复杂,但它*乏味*,有时看起来像是一个错误的东西,这只是忘记携带 n。

因此,我更喜欢使用带有环境名称的固定变量。

于 2013-04-27T04:27:33.573 回答
-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当 eg嵌套在func1whileprova被调用func2(它被调用)时,此解决方案不起作用func1。除非您没有正确更新其参数env...

为了完整起见,根据@RicardoSaporta 的建议,我稍微修改了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))
  # ...
}  

这样,如果pos传入了正确的参数,它在嵌套时也可以工作。

通过这种修改,可以更轻松地找出您在函数上设置属性的环境prova

myfun1 <- function() {
  myattr(prova) <- function() print(FALSE)
  myfun2(n = 2)
}
myfun2 <- function(n) {
  prova(pos = n)
}
myfun1()

# function() print(FALSE)
# <environment: 0x22e8208>
于 2013-04-27T04:59:41.967 回答