From hadley at rice.edu  Wed Sep  9 16:53:33 2009
From: hadley at rice.edu (Hadley Wickham)
Date: Wed, 9 Sep 2009 09:53:33 -0500
Subject: [Rd] Finding the environment of a promise
In-Reply-To: <4AA7B3CA.2080702@stats.uwo.ca>
References: <f8e6ff050909090630t69a76ca7k2c4ea4cc35678d40@mail.gmail.com> 
	<4AA7B3CA.2080702@stats.uwo.ca>
Message-ID: <f8e6ff050909090753w4f5f64d1ka30e480720ddebba@mail.gmail.com>

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

-- 
http://had.co.nz/



[Rd] Finding the environment of a promise
Hadley Wickham