问题描述
我正在尝试创建一个函数,该函数引用调用它的范围以创建唯一 ID:
I'm trying to create a function that references the scope from which it was called to create a unique ID:
uniqueid <- function(name, envir = NULL) {
if(identical(envir, globalenv())) {
e = envir
} else if (is.null(envir)) {
e = parent.frame()
} else if (is.environment(envir)) {
e = envir
} else {
stop("given non-default argument \'envir\' is not an environment")
}
return(paste(sep = "",
sub('<environment: (.*)>', '\\1', capture.output(e)),
".",
name
)
)
}
我该怎么做才能使这项工作按照我认为应该的方式工作?R 不断返回定义函数的作用域,而不是计算函数的作用域:
What can I do to make this work the way I think it should work? R keeps returning the scope in which the function was defined, and not where it is evaluated:
hello <- new.env()
hello$env <- new.env()
eval(envir=hello$env, {
print(environment())
print(hello$env) #hello$env is an environment
print(hello) #hello is an environment
uniqueid('hi')
})
我试图让其中至少一个匹配,但它似乎不想工作.R 要么返回全局环境,要么返回为函数调用实例创建的临时框架/环境的不断变化的范围.ID 需要可在多次调用之间重现并取决于环境.
I'm trying to get at least one of these to match up, but it doesn't seem like it wants to work. R either returns the global environment, or the ever-changing scope of a temporary frame/environment created for an instance of a call to the function. The ID needs to be reproducible between multiple calls and dependent on the environment.
我知道我可以通过环境,但我开始怀疑是否真的可以捕获调用者的环境.
I know I could pass the environment, but I'm beginning to wonder whether doing capture of the caller's environment is actually possible.
推荐答案
TL,DR: parent.frame()
not parent.frame(environment())
;evalq
不是 eval
.
TL,DR: parent.frame()
not parent.frame(environment())
; evalq
not eval
.
parent.frame
接受参数 n
是要返回的代数,而不是 environment()
调用的结果(这是一个环境).如果你把它放在 parent.frame()
调用之外,你就没事了.
parent.frame
takes argument n
being number of generations to go back, not the result of an environment()
call (which is an environment). If you leave it out of the parent.frame()
call you're fine.
此外,您的示例代码并没有像您预期的那样工作,因为您的 environment()
命令在对 eval
的调用中被评估,然后才被评估作为 eval
的一部分.IE.您必须将您的参数引用到 eval
.或者,使用 evalq
而不是 eval
.
Also, yoru example code doesn't work as you expect, because your environment()
command is being evaluated in the call to eval
, before being evaluated as part of eval
. I.e. you must quote your argument to eval
. Alternatively, use evalq
rather than eval
.
例如
uniqueid <- function(name) {
print(parent.frame())
}
hello <- new.env()
hello$env <- new.env()
evalq(envir=hello$env, {
print(environment()) # prints hello$env
print(hello$env) # prints hello$env
print(hello) # prints hello
uniqueid('hi') # prints hello$env
})
例如这将获取环境 ID 并将其添加到 name
:
E.g. this will get the environment ID and add it to the name
:
uniqueid <- function(name) {
# GlobalEnv etc have names; hello doesn't
envName <- environmentName(parent.frame())
# get the environment ID from the parent.frame() output if no name
if (envName == "") {
p <- parent.frame()
envName <- sub('<environment: (.*)>', '\\1', capture.output(p))
}
return(paste(envName, name, sep=':'))
}
uniqueid('x') # R_GlobalEnv:x
print(hello) # <environment: 0x4641fa0>
evalq(envir=hello, uniqueid('x')) # "0x4641fa0:x"
print(hello$env) # <environment: 0x4640e60>
evalq(envir=hello$env, uniqueid('x')) # "0x4640e60:x"
这篇关于R - 如何找到从被调用函数内部调用函数的环境?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!