[Rd] Finding the environment of a promise

Duncan Murdoch murdoch at stats.uwo.ca
Wed Sep 9 17:14:55 CEST 2009


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)
>



More information about the R-devel mailing list