From luke at stat.uiowa.edu  Thu Sep 10 20:46:41 2009
From: luke at stat.uiowa.edu (luke at stat.uiowa.edu)
Date: Thu, 10 Sep 2009 13:46:41 -0500 (CDT)
Subject: [Rd] Finding the environment of a promise
In-Reply-To: <4AA7C66F.8030304@stats.uwo.ca>
References: <f8e6ff050909090630t69a76ca7k2c4ea4cc35678d40@mail.gmail.com>
	<4AA7B3CA.2080702@stats.uwo.ca>
	<f8e6ff050909090753w4f5f64d1ka30e480720ddebba@mail.gmail.com>
	<4AA7C66F.8030304@stats.uwo.ca>
Message-ID: <alpine.LFD.2.00.0909101335060.11471@nokomis.stat.uiowa.edu>

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



[Rd] Finding the environment of a promise
luke at stat.uiowa.edu