Hi, Hadley et al.:

Hadley's link requires his development version of "lazyeval", which can be obtained as follows:


library(devtools)
install_github("hadley/lazyeval")


      Hadley's link describes real problems with elegant solutions.


However, David's solution solved my immediate problem, and it's not immediately obvious to me how his "expr_text" function (or other functions in "lazyevel") to produce a better solution.


      Thanks again to David, Peter and Hadley for their replies.


      Spencer Graves


On 5/6/2016 5:08 PM, Hadley Wickham wrote:
You may want to read http://rpubs.com/hadley/157957, which captures my
latest thinking (and tooling) around this problem. Feedback is much
appreciated.

Hadley

On Fri, May 6, 2016 at 2:14 PM, David Winsemius <dwinsem...@comcast.net> wrote:
On May 6, 2016, at 5:47 AM, Spencer Graves 
<spencer.gra...@effectivedefense.org> wrote:



On 5/6/2016 6:46 AM, peter dalgaard wrote:
On 06 May 2016, at 02:43 , David Winsemius <dwinsem...@comcast.net> wrote:

On May 5, 2016, at 5:12 PM, Spencer Graves 
<spencer.gra...@effectivedefense.org> wrote:

I want a function to evaluate one argument
in the environment of a data.frame supplied
as another argument.  "attach" works for
this, but "with" does not.  Is there a way
to make "with" work?  I'd rather not attach
the data.frame.


With the following two functions "eval.w.attach"
works but "eval.w.with" fails:


dat <- data.frame(a=1:2)
eval.w.attach <- function(x, dat){
  attach(dat)
  X <- x
  detach()
  X
}

eval.w.with <- function(x, dat){
  with(dat, x)
}

eval.w.attach(a/2, dat) # returns c(.5, 1)
How about using eval( substitute( ...))?

eval.w.sub <- function(expr, datt){
   eval( substitute(expr), env=datt)
                         }
eval.w.sub(a/2, dat)
#[1] 0.5 1.0


Actually, I think a better overall strategy is to say that if you want to pass 
an expression to a function, then pass an expression object (or a call object 
or maybe a formula object).

Once you figure out _how_ your eval.w.attach works (sort of), you'll get the 
creeps:

Lazy evaluation causes the argument x to be evaluated after the attach(), hence 
the evaluation environment of an actual argument is being temporarily modified 
from inside a function.

Apart from upsetting computer science purists, there could be hidden problems: One major 
issue is that  values in "dat" could be masked by values in the global 
environment, another issue is that an error in evaluating the expression will leave dat 
attached. So at a minimum, you need to recode using on.exit() magic.

So my preferences go along these lines:

dat <- data.frame(a=1:2)
eval.expression <- function(e, dat) eval(e, dat)
eval.expression(quote(a/2), dat)
[1] 0.5 1.0
eval.expression(expression(a/2), dat)
[1] 0.5 1.0

eval.formula <- function(f, dat) eval(f[[2]], dat)
eval.formula(~a/2, dat)
[1] 0.5 1.0
Hi, Peter:


      I don't like eval.expression or eval.formula, because they don't 
automatically accept what I naively thought should work and require more 
knowledge of the user.  What about David's eval.w.sub:


a <- pi
dat <- data.frame(a=1:2)
eval.w.sub <- function(a, Dat){
  eval( substitute(a), env=Dat)
}
eval.w.sub(a/2, dat)
[1] 0.5 1.0
I liked eval.expression and tested it with a bquote(...) argument to see if that 
would succeed. It did, but it didn't return what you wanted for `a/2`, so I tried 
seeing if a "double eval wuold deliver both yours and my desired results:

  eval.w.sub <- function(a, Dat){
   eval( eval(substitute(a),Dat), env=Dat)
  }
x=2
  eval.w.sub( a/2, dat)
[1] 0.5 1.0
  eval.w.sub( bquote(2*a*.(x) ), dat)
[1] 4 8

We are here retracing the path the Hadley took in some of his ggplot2 design decsions. 
Unfortunately for me those NSE rules often left me confused about what should and 
shouldn't be 'quoted' in the as-character sense and what should be quote()-ed or 
"unquoted" in the bquote() sense.
--



      This produces what's desired in a way that seems simpler to me.


      By the way, I really appreciate Peter's insightful comments:


eval.w.attachOops <- function(x, Dat){
  attach(Dat)
  X <- x
  detach()
  X
}
eval.w.attachOops(a/2, dat)
The following object is masked _by_ .GlobalEnv:

    a

[1] 1.570796
eval.w.attachOops(b/2, dat)
The following object is masked _by_ .GlobalEnv:

    a

Error in eval.w.attachOops(b/2, dat) : object 'b' not found
search()
[1] ".GlobalEnv"        "Dat"               "package:graphics"
[4] "package:grDevices" "package:utils"     "package:datasets"
[7] "package:methods"   "Autoloads"         "package:base"
objects(2)
[1] "a"

*** NOTES:


      1.  This gives a likely wrong answer with a warning if "a" exists in .GlobalEnv, and leaves 
"Dat" (NOT "dat") attached upon exit.



      2.  A stray "detach()" [not shown here] detached "package:stats".  oops.


*** Using "on.exit" fixes the problem with failure to detach but not the likely 
wrong answer:


detach()
search()
eval.w.attachStillWrong <- function(x, dat){
  attach(dat)
  on.exit(detach(dat))
  X <- x
  X
}
The following object is masked _by_ .GlobalEnv:

    a

[1] 1.570796
eval.w.attachStillWrong(b/2, dat)
The following object is masked _by_ .GlobalEnv:

    a

Error in eval.w.attachStillWrong(b/2, dat) : object 'b' not found
search()
[1] ".GlobalEnv"        "package:grDevices" "package:utils"
[4] "package:datasets"  "package:methods"   "Autoloads"
[7] "package:base"


      Thanks again to Peter and David.  Spencer

Peter D.



--
David.


eval.w.with(a/2, dat) # Error ... 'a' not found


Thanks, Spencer Graves

    [[alternative HTML version deleted]]

______________________________________________
R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see
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.
David Winsemius
Alameda, CA, USA

______________________________________________
R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see
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.
David Winsemius
Alameda, CA, USA

______________________________________________
R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see
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@r-project.org mailing list -- To UNSUBSCRIBE and more, see
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.

Reply via email to