[Rd] delayedAssign changing values
peter dalgaard
pdalgd at gmail.com
Fri Apr 27 01:37:53 CEST 2012
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.mes at cbs.dk Priv: PDalgd at gmail.com
More information about the R-devel
mailing list