[Rd] Finding the environment of a promise

Hadley Wickham hadley at rice.edu
Wed Sep 9 16:53:33 CEST 2009


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



More information about the R-devel mailing list