Hi all,
Is it possible to determine the environment in which a promise will be
evaluated? e.g.
f <- function(code) { force(code) }
f({
a <- 1
b <- 2
})
Is there any way to tell from within f that a and b will be created in
the global environment?
Thanks,
Hadley
Finding the environment of a promise
8 messages · Henrique Dallazuanna, Hadley Wickham, Simon Urbanek +2 more
An embedded and charset-unspecified text was scrubbed... Name: not available URL: <https://stat.ethz.ch/pipermail/r-devel/attachments/20090909/6356f19c/attachment.pl>
On 9/9/2009 9:30 AM, Hadley Wickham wrote:
Hi all,
Is it possible to determine the environment in which a promise will be
evaluated? e.g.
f <- function(code) { force(code) }
f({
a <- 1
b <- 2
})
Is there any way to tell from within f that a and b will be created in
the global environment?
I don't think so in R code, but C code to do it would be possible. It needs to be in C code to avoid forcing the promise. I think we'd be reluctant to make an R function available to do this, because it requires non-standard evaluation, and it's not something a normal function should care about. (The promise belongs to the caller, not to the function: why would the function need to play with it? It should be happy with the value, or maybe a text representation of the promise, for labelling purposes.) Duncan Murdoch
I don't think so in R code, but C code to do it would be possible. ?It needs to be in C code to avoid forcing the promise.
Thanks Duncan - I thought that might be the case.
I think we'd be reluctant to make an R function available to do this, because it requires non-standard evaluation, and it's not something a normal function should care about.
True, but there are plenty of abnormal functions in R that demonstrate the usefulness (and danger!) of non-standard evaluation.
?(The promise belongs to the caller, not to the function: ?why would the function need to play with it? ?It should be happy with the value, or maybe a text representation of the promise, for labelling purposes.)
Is there any way to get a text representation apart from with
deparse(substitute(x))? I think I remember asking you about this some
time ago, but it is still the case that blocks/promises don't store
srcref information? This come up recently while trying to make a
function that would both run a block or code and save it to a separate
file (a sort of poor man's sweave when you just want to include a
small portion of your code in a report). With blocks, the best I
could come up with was:
named_block <- function(name, code) {
text <- deparse(substitute(code), width = 100)
# evaluate code
force(code)
# construct valid filename
filename <- gsub("[^a-z0-9]+", "-", tolower(name))
filename <- gsub("^-|-$", "", filename)
filename <- paste(filename, ".r", sep = "")
out <- text[!grepl("\\{|\\}", text)]
out <- gsub("^ ", "", out)
writeLines(out, filename)
}
b <- 1
named_block("test", {
# This is a comment
a <- 1
})
print(a)
The problem of course is that this loses comments.
You can do better with functions, but it requires more typing and
messing around with environments to ensure everything is scoped
correctly:
named_block <- function(name, f) {
text <- attr(f, "source")
code <- text[!grepl("^function \\(\\)\\{$|\\}", text)]
code <- gsub("^ ", "", code)
# evaluate code
eval(parse(text = code), env = parent.frame())
# construct valid filename
filename <- gsub("[^a-z0-9]+", "-", tolower(name))
filename <- gsub("^-|-$", "", filename)
filename <- paste(filename, ".r", sep = "")
writeLines(code, filename)
}
b <- 1
named_block("test", function (){
# This is a comment
a <- 2
})
# Make sure objects created in correct environment
print(a)
On Sep 9, 2009, at 9:40 , Henrique Dallazuanna wrote:
If I understand your question, you can get the environment with
sys.frame:
f <- function(code){
print(sys.frame())
^-- this will always return R_GlobalEnv (see ?sys.frame - which = 0 by default) regardless of the function and promise. Also the question was about the environment of the promise, not the function. Technically a promise can be evaluated anywhere since it ignores the evaluation environment and will use its creation environment which is what Hadley was trying to get at (and as Duncan was saying it's not something that is or should be available at R level as it's an internal implementation detail). Cheers, Simon
force(code)
}
f({
a <- 1
b <- 2
})
On Wed, Sep 9, 2009 at 10:30 AM, Hadley Wickham <hadley at rice.edu>
wrote:
Hi all,
Is it possible to determine the environment in which a promise will
be
evaluated? e.g.
f <- function(code) { force(code) }
f({
a <- 1
b <- 2
})
Is there any way to tell from within f that a and b will be created
in
the global environment?
Thanks,
Hadley
--
http://had.co.nz/
______________________________________________ R-devel at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
-- Henrique Dallazuanna Curitiba-Paran?-Brasil 25? 25' 40" S 49? 16' 22" O [[alternative HTML version deleted]]
______________________________________________ R-devel at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
An embedded and charset-unspecified text was scrubbed... Name: not available URL: <https://stat.ethz.ch/pipermail/r-devel/attachments/20090909/88237ce1/attachment.pl>
On 9/9/2009 10:53 AM, Hadley Wickham wrote:
I don't think so in R code, but C code to do it would be possible. It needs to be in C code to avoid forcing the promise.
Thanks Duncan - I thought that might be the case.
I think we'd be reluctant to make an R function available to do this, because it requires non-standard evaluation, and it's not something a normal function should care about.
True, but there are plenty of abnormal functions in R that demonstrate the usefulness (and danger!) of non-standard evaluation.
(The promise belongs to the caller, not to the function: why would the function need to play with it? It should be happy with the value, or maybe a text representation of the promise, for labelling purposes.)
Is there any way to get a text representation apart from with deparse(substitute(x))? I think I remember asking you about this some time ago, but it is still the case that blocks/promises don't store srcref information? This come up recently while trying to make a function that would both run a block or code and save it to a separate file (a sort of poor man's sweave when you just want to include a small portion of your code in a report). With blocks, the best I could come up with was:
Promises don't store srcrefs, but the evaluator does (in R-devel), a statement at a time. So you might be able to look back through the call stack to find where the call came from. (I forget whether any of this is accessible from within R. Look at the implementation of traceback() and browser(), which both access this information.) Duncan Murdoch
named_block <- function(name, code) {
text <- deparse(substitute(code), width = 100)
# evaluate code
force(code)
# construct valid filename
filename <- gsub("[^a-z0-9]+", "-", tolower(name))
filename <- gsub("^-|-$", "", filename)
filename <- paste(filename, ".r", sep = "")
out <- text[!grepl("\\{|\\}", text)]
out <- gsub("^ ", "", out)
writeLines(out, filename)
}
b <- 1
named_block("test", {
# This is a comment
a <- 1
})
print(a)
The problem of course is that this loses comments.
You can do better with functions, but it requires more typing and
messing around with environments to ensure everything is scoped
correctly:
named_block <- function(name, f) {
text <- attr(f, "source")
code <- text[!grepl("^function \\(\\)\\{$|\\}", text)]
code <- gsub("^ ", "", code)
# evaluate code
eval(parse(text = code), env = parent.frame())
# construct valid filename
filename <- gsub("[^a-z0-9]+", "-", tolower(name))
filename <- gsub("^-|-$", "", filename)
filename <- paste(filename, ".r", sep = "")
writeLines(code, filename)
}
b <- 1
named_block("test", function (){
# This is a comment
a <- 2
})
# Make sure objects created in correct environment
print(a)
1 day later
One of the (many) things on my TODO list is to add some sort of
reflection mechanism for examinging the status of bindings --
standard, active, delayed but evaluated, delayed but not yet
evaluated, etc. The interface might have a flavor like
bindingStatus(name, envir) returns one of "standard", "delayed",
"delayed-evaluated"
or something along these lines. It is important not to think in terms
of promises, which happen to exist as internal implementation devices
at the moment but might not in the future.
For cases like delayed but not yet evaluated it may make sense to also
provide access to things like the expression or code (which need not
be the same), or the environment. But there are some issues. For
example, once a delayed assignment is evaluated the environment is no
longer needed, and dropping it povides opportunities for memory
reclamation (the interpreter does this now by setting the environment
field of a promise to NULL once the promise is evaluated). We
wouldn't want a reflection mechanism to make tha impossible. Also, in
cases like a call f(1) there is no good reason for creating a delayed
evaluation, since the result of evaluating the argument is clear. The
interpreter doesn't do such an optimization at this time but it might
be useful in the future, and again we would not want a reflection
mechanism to get in the way of this.
So it's worth thinking about, especially if a compelling use case is
available, but there are subtleties and it would not be a good idea to
move too hastily.
Best,
luke
On Wed, 9 Sep 2009, Duncan Murdoch wrote:
On 9/9/2009 10:53 AM, Hadley Wickham wrote:
I don't think so in R code, but C code to do it would be possible. It needs to be in C code to avoid forcing the promise.
Thanks Duncan - I thought that might be the case.
I think we'd be reluctant to make an R function available to do this, because it requires non-standard evaluation, and it's not something a normal function should care about.
True, but there are plenty of abnormal functions in R that demonstrate the usefulness (and danger!) of non-standard evaluation.
(The promise belongs to the caller, not to the function: why would the function need to play with it? It should be happy with the value, or maybe a text representation of the promise, for labelling purposes.)
Is there any way to get a text representation apart from with deparse(substitute(x))? I think I remember asking you about this some time ago, but it is still the case that blocks/promises don't store srcref information? This come up recently while trying to make a function that would both run a block or code and save it to a separate file (a sort of poor man's sweave when you just want to include a small portion of your code in a report). With blocks, the best I could come up with was:
Promises don't store srcrefs, but the evaluator does (in R-devel), a statement at a time. So you might be able to look back through the call stack to find where the call came from. (I forget whether any of this is accessible from within R. Look at the implementation of traceback() and browser(), which both access this information.) Duncan Murdoch
named_block <- function(name, code) {
text <- deparse(substitute(code), width = 100)
# evaluate code
force(code)
# construct valid filename
filename <- gsub("[^a-z0-9]+", "-", tolower(name))
filename <- gsub("^-|-$", "", filename)
filename <- paste(filename, ".r", sep = "")
out <- text[!grepl("\\{|\\}", text)]
out <- gsub("^ ", "", out)
writeLines(out, filename)
}
b <- 1
named_block("test", {
# This is a comment
a <- 1
})
print(a)
The problem of course is that this loses comments.
You can do better with functions, but it requires more typing and
messing around with environments to ensure everything is scoped
correctly:
named_block <- function(name, f) {
text <- attr(f, "source")
code <- text[!grepl("^function \\(\\)\\{$|\\}", text)]
code <- gsub("^ ", "", code)
# evaluate code
eval(parse(text = code), env = parent.frame())
# construct valid filename
filename <- gsub("[^a-z0-9]+", "-", tolower(name))
filename <- gsub("^-|-$", "", filename)
filename <- paste(filename, ".r", sep = "")
writeLines(code, filename)
}
b <- 1
named_block("test", function (){
# This is a comment
a <- 2
})
# Make sure objects created in correct environment
print(a)
______________________________________________ R-devel at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Luke Tierney
Chair, Statistics and Actuarial Science
Ralph E. Wareham Professor of Mathematical Sciences
University of Iowa Phone: 319-335-3386
Department of Statistics and Fax: 319-335-3017
Actuarial Science
241 Schaeffer Hall email: luke at stat.uiowa.edu
Iowa City, IA 52242 WWW: http://www.stat.uiowa.edu