On Thu, Oct 21, 2021 at 12:15 PM Rolf Turner <r.tur...@auckland.ac.nz> wrote: > > > On Thu, 21 Oct 2021 02:03:41 -0400 > Duncan Murdoch <murdoch.dun...@gmail.com> wrote: > > > On 21/10/2021 12:40 a.m., Andrew Simmons wrote: > > > I think the simplest answer is to store the variable in the > > > functions frame. I'm assuming here that the only plot.foo needs > > > access to .fooInfo, if not this can be changed. > > > > > > > > > plot.foo <- function (...) > > > { > > > .fooInfo > > > } > > > environment(plot.foo) <- new.env() > > > evalq({ > > > .fooInfo <- NULL > > > }, environment(plot.foo)) > > > > > > > > > Make your function, and do whatever you need with .fooInfo within > > > said function. Whenever you previously updated .fooInfo in the > > > global environment, update .fooInfo in plot.foo environment instead. > > > Also, because .fooInfo is not stored in the package's frame, it > > > won't be locked when the namespace is sealed. If you created it at > > > the toplevel, that would create some issues. But this works fine. > > > > I agree with the final result, but I'd write the code differently: > > > > plot.foo <- local({ > > > > .fooInfo <- NULL > > > > function (...) { ... } > > }) > > > > creates an environment, puts .fooInfo into it with value NULL, then > > creates a function with that environment attached and returns it. > > > > I think Andrew's approach will work, but changing a function's > > environment always worries me. Using local(), the function assigned > > to plot.foo never has a different environment than the one it ends up > > with (and I don't need to remember how evalq() works). > > Thanks everyone for these suggestions. They seem a great deal > less shaganappi/kludgy than my previous approaches. > > I've never really felt totally comfortable with the environment > concept, despite have used it quite a bit (basically in a > hammer-and-hope style.) > > Can anyone comment on the difference between Deepayan's suggestion > (create a new environment in the package) and Duncan's suggestion > (create an environment that is local to plot.foo())? Are there pros > and cons between the two?
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'm not sure what you are trying to do, but I can't see how you can do something sensible with a function-specific environment if someone does plot.foo(something) plot.default(1:10) plot.foo(something else, add = TRUE) So maybe you would eventually want to set a hook (?setHook) for plot.new to ensure that no other plot has been created in between, which could write into this package-specific environment. > And Deepayan: what is the rationale for not exporting the new > environment that you suggest creating? Presumably this guards against > something. What? I'd just like to extend my (currently minimal) > comprehension of the issues. Nothing other than the usual reason for not exporting things unnecessarily, which is to not pollute the user workspace. > I must admit that Andrew's suggestion kind of overwhelms and bewilders > me. I really have no idea what evalq() does. I guess I could RTFM, > but the thought of doing that scares me! :-) Andrew's suggestion looks more complicated than it is. Think of .fooInfo as a "global" variable, just in your package namespace rather than .GlobalEnv, so you could do (in your package code) .fooInfo <- NULL plot.foo <- function(...) { if (is.null(.fooInfo)) ... # use .fooInfo .fooInfo <<- something # set .fooInfo } Andrew suggested a separate (and unnamed) environment to store both .fooInfo and plot.foo, so the setting part becomes a bit more complicated (but accessing becomes safer in the sense that no other function can access .fooInfo). My suggestion is essentially similar, except that you can use <- instead of <<- because it's an environment. .fooEnv <- new.env() plot.foo <- function(...) { if (is.null(.fooEnv$info)) ... # use .fooEnv$info .fooEnv$info <- something # set .fooEnv$info } Best, -Deepayan > Thanks again everybody. > > cheers, > > Rolf > > -- > Honorary Research Fellow > Department of Statistics > University of Auckland > Phone: +64-9-373-7599 ext. 88276 > ______________________________________________ R-package-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-package-devel