Skip to content
Prev 316329 / 398502 Next

parse/eval and character encoded expressions: How to deal with non-encoding strings?

Instead of saving a string that can be parsed into a language object (and
later evaluated), I would just save something that that could be evaluated
directly.  Note that a literal like "MyFile" or 3.14 evaluates to itself so you
can save a literal string or a language object and use eval() on either.  Unless
you do this there is no good way to know if "TestDir/TestFile*.txt" means to
do some multiplication and division or to use a glob pattern to find a group of files.
E.g.,

  makeFoo <- function(file, ...) {
      structure(c(...), fileExpr=substitute(file), class="Foo")
  }
  getFileFoo <- function(FooObject) {
      eval(attr(FooObject, "fileExpr"))
  }

used as

  > z <- makeFoo(system.file(package="fpp", "DESCRIPTION"), 1, 2, 3)
  > z
  [1] 1 2 3
  attr(,"fileExpr")
  system.file(package = "fpp", "DESCRIPTION")
  attr(,"class")
  [1] "Foo"
  > getFileFoo(z)
  [1] "C:/Program Files/R/R-2.15.2/library/fpp/DESCRIPTION"
or
  > z <- makeFoo("C:/Temp/File.txt", 1, 2, 3)
  > z
  [1] 1 2 3
  attr(,"fileExpr")
  [1] "C:/Temp/File.txt"
  attr(,"class")
  [1] "Foo"
  > getFileFoo(z)
  [1] "C:/Temp/File.txt"

One thing you might worry about is in which environment the language object is
evaluated (the envir= argument to eval()).  If you embed your object in a formula
then environment(formula) tells you where to evaluate it.  If the formula syntax
is distracting then you can attach an attribribute called ".Environment" to your object
that environment(object) will retrieve.  E.g.,

    makeFooEnv <- function(file, ..., envir = parent.frame()) {
         fileExpr <- structure(substitute(file), .Environment = envir)
         structure(c(...), fileExpr = fileExpr, class="Foo")
    }
    getFileFoo <- function(FooObject) {
         fileExpr <- attr(FooObject, "fileExpr")
         eval(fileExpr, envir=environment(fileExpr))
    }

used as
  > fooObjs <- lapply(1:3, function(i)makeFooEnv(paste0("File",i,".txt"), i^2))
  > fooObjs[[2]]
  [1] 4
  attr(,"fileExpr")
  paste0("File", i, ".txt")
  attr(,"fileExpr")attr(,".Environment")
  <environment: 0x000000000b7f8998>
  attr(,"class")
  [1] "Foo"
  > 
  > i <- 17
  > getFileFoo(fooObjs[[2]]) # Note that eval gets value of i as 2, not 17
  [1] "File2.txt"

Bill Dunlap
Spotfire, TIBCO Software
wdunlap tibco.com