简体   繁体   中英

How can I write code containing comments to a file, using an R function?

I am trying to write an Rscript from within R. Using quote() with the $wholeSrcref attribute works well when on its own. However, additional unwanted lines are written when used within a function. Details are as provided below.

My first attempt was to quote() the expression, followed by writing the quoted expression to file, that is,

expr <- quote({
  a <- 1 # comment 1
  b <- 2 # comment 2
})
writeLines(tail(as.character(expr), -1), file)

However, comments in the code are not written to file. A workaround would be to use the $wholeSrcref attribute, as given by this answer . My second attempt:

library(magrittr)
expr <- quote({
  a <- 1 # comment 1
  b <- 2 # comment 2
})
attributes(expr)$wholeSrcref %>% as.character() %>%
  tail(-1) %>%  # remove '{'
  head(-1) %>%  # remove '}'
writeLines(file)

This works well. However, when wrapping this within a function, part of the function's body is also prepended to the quoted expression. That is, given the following code,

library(magrittr)
f <- function(dir) {
  # change directory to dir
  # do stuff

  expr <- quote({
    a <- 1 # comment 1
    b <- 2 # comment 2
  })

  attributes(expr)$wholeSrcref %>% as.character() %>%
    tail(-1) %>%  # remove '{'
    head(-1) %>%  # remove '}'
  writeLines(file)

  # do more stuff
}
f(dir="")

The file would contain

  # change directory to dir 
  # do stuff 

  expr <- quote({
    a <- 1 # comment 1
    b <- 2 # comment 2

How can I write only the quoted expression to file?

Well, the easiest approach would be to count the lines above the quote function and adjust the tail function to exclude these rows. Admittedly, it's not very elegant

f <- function(dir) {
  # change directory to dir
  # do stuff
  
  expr <- quote({
    a <- 1 # comment 1
    b <- 2 # comment 2
  })
  exclusion_line <- which(grepl("expr <- quote({",
                               attributes(expr)$wholeSrcref %>% as.character(),
                               fixed = TRUE))
  attributes(expr)$wholeSrcref %>% as.character() %>%
    tail(-exclusion_line) %>%  # remove '{'
    head(-1) %>%  # remove '}'
    writeLines(file)
  
  # do more stuff
}
f(dir="")

One way to approach this, as user starja pointed out in his answer , is to find the start of the quoted expression. In the example given in the question, one can search for "expr <- quote({" , as in:

  expr_ref <- attributes(expr)$wholeSrcref %>% as.character()
  exclusion_line <- grep("expr <- quote({", 
                         expr_ref, fixed = TRUE) 

  expr_ref %>%
    tail(-exclusion_line) %>%  # remove up till '{'
    head(-1) %>%  # remove '}'
    writeLines(file)

One caveat is the hard coded "expr <- quote({" . What if we wanted to use another variable name other than "expr" ?. We place the above code in a function and modify it with deparse(substitute(...)) , ie

write_expr <- function(expr, file) {

  expr_name <- deparse(substitute(expr))
  expr_ref <- attr(expr, "wholeSrcref") %>% as.character()
  exclusion_line <- grep(paste0("^\\s*", expr_name, "\\s*<-"), expr_ref)

 expr_ref %>%
    tail(-exclusion_line) %>%  # remove up till '{'
    head(-1) %>%  # remove '}'
    writeLines(file)
}

and modify the f to become

f <- function(dir) {
  # change directory to dir
  # do stuff
  
  some_expr <- quote({
    a <- 1 # comment 1
    b <- 2 # comment 2
  })
  write_expr(some_expr, file)

  # do more stuff
}

Now, upon calling f() , the file contains

    a <- 1 # comment 1
    b <- 2 # comment 2

as desired.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM