scope - R - How to find the environment where a function is called from inside the called function? -
i'm trying create function references scope called create 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\' not environment") } return(paste(sep = "", sub('<environment: (.*)>', '\\1', capture.output(e)), ".", name ) ) } what can make work way think should work? r keeps returning scope in function defined, , not evaluated:
hello <- new.env() hello$env <- new.env() eval(envir=hello$env, { print(environment()) print(hello$env) #hello$env environment print(hello) #hello environment uniqueid('hi') }) i'm trying @ least 1 of these match up, doesn't seem wants work. r either returns global environment, or ever-changing scope of temporary frame/environment created instance of call function. id needs reproducible between multiple calls , dependent on environment.
i know pass environment, i'm beginning wonder whether doing capture of caller's environment possible.
tl,dr: parent.frame() not parent.frame(environment()); evalq not eval.
parent.frame takes argument n being number of generations go back, not result of environment() call (which environment). if leave out of parent.frame() call you're fine.
also, yoru example code doesn't work expect, because environment() command being evaluated in call eval, before being evaluated as part of eval. i.e. must quote argument eval. alternatively, use evalq rather eval.
e.g.
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 }) e.g. environment id , add name:
uniqueid <- function(name) { # globalenv etc have names; hello doesn't envname <- environmentname(parent.frame()) # environment id 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"
Comments
Post a Comment