[R] Environmental problems.
Duncan Murdoch
murdoch.duncan at gmail.com
Tue Feb 25 13:13:55 CET 2014
On 14-02-25 3:08 AM, Rolf Turner wrote:
>
> I have a function that makes use of the ode() function from the
> "deSolve" package. I am trying to find a way of getting it to put out a
> "progress report" every "t.int" time units (by "progress report" I just
> mean reporting what time it's got up to).
>
> I thought to put code something like the following in my "func" function
> that gets called by (is an argument to) ode():
>
>> cat("Before: time =",tt,"tdone =",tdone,"diff =",tt-tdone,"\n")
>> if(tt - tdone >= 0.1-sqrt(.Machine$double.eps)) {
>> cat("Prog. Rep.: time =",tt,"tdone =",tdone,"diff =",tt-tdone,"\n")
>> assign("tdone",tt,envir=parent.env(environment()))
>> }
>> cat("After: time =",tt,"tdone =",tdone,"diff =",tt-tdone,"\n")
>
> The object "tdone" gets initialized (to 0) outside of func(), so there
> is not a problem with "tdone" not being found the first time that func()
> gets called by ode(). (I'm hardwiring "t.int=0.1" in the forgoing just
> for test/illustration purposes.) The "Before" and "After" cat()-s are
> there to demonstrate what goes wrong.
>
> What goes wrong is that I get no progress report and tdone remains equal
> to 0 until tt reaches 0.1. As desired. I then get a progress report and
> tdone gets set equal to the first value of tt which is greater than 0.1.
> As desired.
>
> Then I get no further progress reports and tdone gets set equal to tt at
> every call to func() --- even though tt - tdone = 0 which is less than
> 0.1 so the assignment of tdone cannot occur. And yet it does, keeping
> the difference equal to 0. (*Not* as desired!)
>
> So the function is recognizing that the difference is less than 0.1 in
> that it does not execute the cat() statement. Yet it executes the
> assign() statement. This is clearly impossible! :-) But it happens.
>
> The output from the cat()-ing, around time = 0.1, looks like:
>
>> Before: time = 0.09364548 tdone = 0 diff = 0.09364548
>> After: time = 0.09364548 tdone = 0 diff = 0.09364548
>> Before: time = 0.0975779 tdone = 0 diff = 0.0975779
>> After: time = 0.0975779 tdone = 0 diff = 0.0975779
>> Before: time = 0.0975779 tdone = 0 diff = 0.0975779
>> After: time = 0.0975779 tdone = 0 diff = 0.0975779
>> Before: time = 0.09698997 tdone = 0 diff = 0.09698997
>> After: time = 0.09698997 tdone = 0 diff = 0.09698997
>> Before: time = 0.1009224 tdone = 0 diff = 0.1009224
>> Prog. Rep.: time = 0.1009224 tdone = 0 diff = 0.1009224
>> After: time = 0.1009224 tdone = 0.1009224 diff = 0
>> Before: time = 0.1009224 tdone = 0.1009224 diff = 0
>> After: time = 0.1009224 tdone = 0.1009224 diff = 0
>> Before: time = 0.1003344 tdone = 0.1003344 diff = 0 <--------------|
>> After: time = 0.1003344 tdone = 0.1003344 diff = 0
>> Before: time = 0.1042669 tdone = 0.1042669 diff = 0
>> After: time = 0.1042669 tdone = 0.1042669 diff = 0
>
> It's at that line indicated by "<----|", 4 lines from the bottom of the
> forgoing display, where things go to hell in a handcart. Why (how on
> earth can) tdone change from 0.1009224 to 0.1003344, given that the
> difference is 0 whence no assignment of tdone should take place?
>
> What am I not seeing? Can anyone help me out? I'm going mad!
> ***MAD*** I tell you! :-)
>
> Suggestions as to a better way of accomplishing my desired goal of
> producing progress reports would also be welcome.
>
> I am not at all sure that assigning "tdone" in parent.env(environment())
> is the right thing to do. I need to assign it in such a way and in such
> a location that its value will persist
> from call to call of "func". Words of wisdom about this would be
> gratefully received. (I don't really grok environments. I just try
> things until *something* works!)
You don't show us everything (we want the full Monty!), so it's hard to
say what's going wrong. My guess would be that you have both a local
copy as well as a parent copy of some variable, and your test is
consulting the wrong one.
A better approach to what you are doing (better since yours modifies
things in the global environment, and that can be dangerous; other code
might modify it too) is the following. Create your func in a local
block, and it will have it's own mini-environment associated with it.
Put tdone there. For example,
func <- local({
# local() creates an environment; that's where tdone will live
tdone <- 0
# this function's environment will be the one created by
# local(), so it will see tdone, but other code won't see it.
function(x) {
# the timing stuff
tt <- Sys.time()
if (tt - tdone > 0.1) {
cat("Prog rep...")
tdone <<- tt
}
# now the real stuff
...
})
Duncan Murdoch
More information about the R-help
mailing list