>>>>> Duncan Murdoch >>>>> on Thu, 21 Oct 2021 08:09:02 -0400 writes:
> I agree with almost everything Deepayan said, but would add one thing: > On 21/10/2021 3:41 a.m., Deepayan Sarkar wrote: > ... >> My suggestion is having a package-specific environment, and Duncan's >> is to have a function-specific environment. If you only need this for >> this one function, then that should be good enough. If you eventually >> want to access the persistent information from multiple functions, >> having a package-specific environment would be more useful. > I agree with that statement, but those aren't the only two choices. > Your local() call can create several functions and return them in a > list; then just those functions have access to the local variables. For > example, > createFns <- local({ > .fooInfo <- NULL > fn1 <- function (...) { ... } > fn2 <- function (...) { ... } > list(fn1 = fn1, fn2 = fn2) > }) > fns <- createFns() > fn1 <- fns$fn1 > fn2 <- fns$fn2 > Now fn1 and fn2 are functions that can see .fooInfo, and nobody else can > (without going through contortions). > One other difference between this approach and the package-specific > environment: there's only one package-specific environment in > Deepayan's formulation, but I could call createFns() several times, > creating several pairs of functions, each pair with its own independent > version of .fooInfo. > I don't know if that's something that would be useful to you, but > conceivably you'd want to maintain partial plots in several different > windows, and that would allow you to do so. Note that the above approach has been how nls() has been implemented for R ... a very long time ago {before R 1.0.0} e.g. from example(nls) : DNase1 <- subset(DNase, Run == 1) fm1 <- nls(density ~ SSlogis(log(conc), Asym, xmid, scal), DNase1) str(fm1 $ m) > List of 16 > $ resid :function () > $ fitted :function () > $ formula :function () > $ deviance :function () > $ lhs :function () > $ gradient :function () > $ conv :function () > $ incr :function () > $ setVarying:function (vary = rep_len(TRUE, np)) > $ setPars :function (newPars) > $ getPars :function () > $ getAllPars:function () > $ getEnv :function () > $ trace :function () > $ Rmat :function () > $ predict :function (newdata = list(), qr = FALSE) > - attr(*, "class")= chr "nlsModel" ## so 16 functions, all sharing the *same* environment very ## efficiently and nicely ## this is *the* environment for the fitted model : fmE <- environment(fm1$m[[1]]) ls.str(fmE) > convCrit : function () > dev : num 0.00479 > env : <environment: 0x106c88a0> > form : Class 'formula' language density ~ SSlogis(log(conc), Asym, xmid, > scal) > getPars : function () > .... > .... > .... so the environment "contains" the functions themselves (but quite a few more things) and for an environment that means it only has pointers to the same function objects which are *also* in `fm1$m`. So, there has been a nice convincing and important example on how to do this - inside R for more than two decennia. Martin Maechler ______________________________________________ R-package-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-package-devel