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

William Dunlap wdunlap at tibco.com
Mon Jan 28 17:40:15 CET 2013


I said
> you can attach an attribribute called ".Environment" to your object
> that environment(object) will retrieve

You can also use
   environment(object) <- envir
instead of
   object <- structure(object, .Environment = envir)
to set the ".Environment" attribute to envir.  This makes the code more
symmetric and you don't have remember the magic attribute name.

Bill Dunlap
Spotfire, TIBCO Software
wdunlap tibco.com


> -----Original Message-----
> From: r-help-bounces at r-project.org [mailto:r-help-bounces at r-project.org] On Behalf
> Of William Dunlap
> Sent: Monday, January 28, 2013 8:14 AM
> To: Johannes Graumann; r-help at stat.math.ethz.ch
> Subject: Re: [R] 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
> 
> > -----Original Message-----
> > From: r-help-bounces at r-project.org [mailto:r-help-bounces at r-project.org] On Behalf
> > Of Johannes Graumann
> > Sent: Sunday, January 27, 2013 11:29 PM
> > To: r-help at stat.math.ethz.ch
> > Subject: [R] parse/eval and character encoded expressions: How to deal with non-
> > encoding strings?
> >
> > Hi,
> >
> > I am intending to save a path-describing character object in a slot of a
> > class I'm working on. In order to have the option to use "system.file" etc
> > in such string-saved path definitions, I wrote this
> >
> > ExpressionEvaluator <- function(x){
> >   x <- tryCatch(
> >     expr=base::parse(text=x),
> >     error = function(e){return(as.expression(x))},
> >     finally=TRUE)
> >   return(x)
> > }
> >
> > This produces
> >
> > > ExpressionEvaluator("system.file(\"INDEX\")")
> > expression(system.file("INDEX"))
> > > eval(ExpressionEvaluator("system.file(\"INDEX\")"))
> > [1] "/usr/lib/R/library/base/INDEX"
> >
> > Which is what I want. However,
> >
> > > eval(ExpressionEvaluator("Test"))
> > Error in eval(expr, envir, enclos) : object 'Test' not found
> >
> > prevents me from general usage (also in cases where "x" does NOT encode an
> > expression).
> >
> > I don't understand why it is that
> > > base::parse(text="Test")
> > will return
> > [1] expression(Test)
> > while
> > > as.expression("Test")
> > produces
> > [1] expression("Test")
> > which would work with the eval call.
> >
> > Can anyone point out to me how to solve this generally? How can I feed the
> > function a character object and get back an eval-able expression independent
> > of whether there was an expression "encoded" in the input or not.
> >
> > Thank you for any hints.
> >
> > Sincerely, Joh
> >
> > ______________________________________________
> > R-help at r-project.org mailing list
> > https://stat.ethz.ch/mailman/listinfo/r-help
> > PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
> > and provide commented, minimal, self-contained, reproducible code.
> 
> ______________________________________________
> R-help at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
> and provide commented, minimal, self-contained, reproducible code.



More information about the R-help mailing list