On Apr 27, 2012, at 00:10 , ghostwheel wrote: > > Simon Urbanek wrote >> >>> More intuitive would have been the behavior >>> delayedAssign("x", local({y <- 7; y+3}) ) >>> which only changes x. >> >> That is questionable - I think it is more logical for both environments to >> be the same as default. Just think if it -- the point here is to access >> lazy evaluation which is exactly what it does - lazy evaluation takes >> place in the original environment, not in another one. >> > > I think I finally understand. My intuition just came from looking at > ?delayedAssign. > But delayedAssign came to replace delay(), which "creates a promise to > evaluate the given expression". > When one thinks of delay(), what you said makes sense, you just delay > executing a certain expression in the parent frame. > > I think, though, that with the current way it is described and called, > delayedAssign should by default only have the side effect of changing the > variable, i.e. use eval.env=new.env().
That's not possible. It involves evaluating an expression, and there is no limit to what side effect this can have. > > The manual states: > This function is invoked for its side effect, which is assigning a promise > to evaluate value to the variable x. > > I think that is a nice clear side effect - changing a variable when it is > evaluated...like a delayed "<<-". > Otherwise it seems to me that delayedAssign could cause debugging > nightmares. Luckily, it currently doesn't seem to widely used to cause > them.... Just don't do that, then.... However, lazy evaluation _per se_ does cause nightmares, or at least surprising behavior. My favorite one (because it actually involves a relevant piece of statistics) is loglike <- function(x,n) function(p) dbinom(x, n, p, log=TRUE) n <- 10 x <- 7 ll <- loglike(x, n) x <- 1 curve(ll) # max at 0.1 which has the issue that x (and n too) is not evaluated until the ll function is called, at which time it may have been changed from the value it had when ll was created. > > But you are right that it might be a bit strange that assign.env and > eval.env are different. Maybe that is why there are two different parameters > - to make the side effects clearer? > I tried to find anywhere uses of delayedAssign which make positive use of > side effects other than the assignment, and couldn't find any. Does anyone > know of such a use? > They'll have to be rather contrived, but printing is one, and perhaps maintaining a count of function calls could be another. > P.S. the end of ?delayedAssign contains this cryptic code: > > e <- (function(x, y = 1, z) environment())(1+2, "y", {cat(" HO! "); pi+2}) > (le <- as.list(e)) # evaluates the promises > > Which I think is another way to create a promise, other than delayedAssign. > But it is really unclear why it sits there at the bottom of the document. > There should probably be more explanation of what this is.... It's actually the _normal_ way to create a promise, namely binding actual arguments to formal arguments. It is just that some trickery is used in order to make the situation visible. I agree that the example looks a bit out of place, though. Perhaps there ought to be a help page on lazy evaluation and a reference to it? (Any volunteers?) -- Peter Dalgaard, Professor, Center for Statistics, Copenhagen Business School Solbjerg Plads 3, 2000 Frederiksberg, Denmark Phone: (+45)38153501 Email: pd....@cbs.dk Priv: pda...@gmail.com ______________________________________________ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel