On 21/03/2016 11:19 AM, Bert Gunter wrote:
Martin, All:

A very nice point! Perhaps the following may help to illustrate it.

g <- function(){
   x <- NULL
   function(y){cat("result is ",x," \n"); x <<- y}
}


> f <- g()

> rm(g) # g is deleted but its environment remains as the environment of f

That's not quite the jargon we use. The environment of g would probably be the global environment. The thing that gets left behind is the evaluation frame (or environment) of the call g(). Its parent environment is the environment of g.

Duncan Murdoch

> f(1)
result is

> f(3)
result is  1

> f(5)
result is  3


Best,
Bert





Bert Gunter

"The trouble with having an open mind is that people keep coming along
and sticking things into it."
-- Opus (aka Berkeley Breathed in his "Bloom County" comic strip )


On Mon, Mar 21, 2016 at 2:41 AM, Martin Maechler
<maech...@stat.math.ethz.ch> wrote:
>>>>>> Duncan Murdoch <murdoch.dun...@gmail.com>
>>>>>>     on Sat, 19 Mar 2016 17:57:56 -0400 writes:
>
>     > On 19/03/2016 12:45 PM, Boris Steipe wrote:
>     >> Dear all -
>     >>
>     >> I need to have a function maintain a persistent lookup table of 
results for an expensive calculation, a named vector or hash. I know that I can just 
keep the table in the global environment. One problem with this approach is that the 
function should be able to delete/recalculate the table and I don't like side-effects in 
the global environment. This table really should be private. What I don't know is:
>     >> -A- how can I keep the table in an environment that is private to the 
function but persistent for the session?
>     >> -B- how can I store and reload such table?
>     >> -C- most importantly: is that the right strategy to initialize and 
maintain state in a function in the first place?
>     >>
>     >>
>     >> For illustration ...
>     >>
>     >> -----------------------------------
>     >>
>     >> myDist <- function(a, b) {
>     >> # retrieve or calculate distances
>     >> if (!exists("Vals")) {
>     >> Vals <<- numeric() # the lookup table for distance values
>     >> # here, created in the global env.
>     >> }
>     >> key <- sprintf("X%d.%d", a, b)
>     >> thisDist <- Vals[key]
>     >> if (is.na(thisDist)) {          # Hasn't been calculated yet ...
>     >> cat("Calculating ... ")
>     >> thisDist <- sqrt(a^2 + b^2) # calculate with some expensive function 
...
>     >> Vals[key] <<- thisDist      # store in global table
>     >> }
>     >> return(thisDist)
>     >> }
>     >>
>     >>
>     >> # run this
>     >> set.seed(112358)
>     >>
>     >> for (i in 1:10) {
>     >> x <- sample(1:3, 2)
>     >> print(sprintf("d(%d, %d) = %f", x[1], x[2], myDist(x[1], x[2])))
>     >> }
>
>
>     > Use local() to create a persistent environment for the function.  For
>     > example:
>
>     > f <- local({
>     > x <- NULL
>     > function(y) {
>     > cat("last x was ", x, "\n")
>     > x <<- y
>     > }
>     > })
>
>     > Then:
>
>     >> f(3)
>     > last x was
>     >> f(4)
>     > last x was  3
>     >> f(12)
>     > last x was  4
>
>     > Duncan Murdoch
>
> Yes, indeed.
> Or use another function {than 'local()'} which returns a
> function:  The functions  approxfun(), splinefun() and ecdf()
> are "base R" functions which return functions "with a
> non-trivial environment" as I use to say.
>
> Note that this is *the* proper R way solving your problem.
>
> The fact that this works as it works is called "lexical scoping"
> and also the reason why (((regular, i.e., non-primitive)))
> functions in R are called closures.
> When R was created > 20 years ago, this has been the
> distinguishing language feature of R (in comparison to S / S-plus).
>
> Enjoy! - Martin
>
> ______________________________________________
> 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