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@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel

Reply via email to