Thanks for this. Also Duncan's description of how code in the R directory is executed.
I've more or less figured out a workaround. Unfortunately Georgi's solution doesn't quite do the trick. Here is my current understanding and solution. Issue: I want to get root of a function of 1 parameter x, but there may be exogenous data Xdata. I also want to count the evaluations. Some rootfinders don't have counter and some don't allow "..." Initial solution: Create global envroot with counters and such. Put name of function and gradient in there, then use a dummy FnTrace (and possibly grTrace). This gave various check complaints about globals etc. However, does appear to work. Present approach: Slightly less flexible, but no complaints. Within rootwrap() which calls different rootfinders according to method="name", define FnTrace and grTrace, set up a list glist for the items I want to share, then envroot <- list2env(glist) The FnTrace and grTrace are defined before the calls to rootfinders, so envroot can be found. No globals. R CMD check is happy. However, I must call rootfinders via the wrapper, which is actually simpler from point of view of syntax. I've still some testing and tweaking, but I think main issues resolved by this. Thanks to all who responded. JN On 2018-08-28 12:27 PM, Georgi Boshnakov wrote: > If you don't insist on putting the variable in the global environment, > variations of the following give a cleaner solution: > > TraceSetup_1 <- local({ > ifn = 0 > igr = 0 > ftrace = FALSE > fn = NA > gr = NA > > function(ifn=0, igr=0, ftrace=FALSE, fn=NA, gr=NA){ > ifn <<- ifn > igr <<- igr > ftrace <<- ftrace > fn <<- fn > gr <<- gr > parent.env(environment()) > } > }) > > For example, > > TraceSetup_1 <- local({ > + ifn = 0 > + igr = 0 > + ftrace = FALSE > + fn = NA > + gr = NA > + function(ifn=0, igr=0, ftrace=FALSE, fn=NA, gr=NA){ > + ifn <<- ifn > + igr <<- igr > + ftrace <<- ftrace > + fn <<- fn > + gr <<- gr > + parent.env(environment()) > + } > + }) >> >> e <- TraceSetup_1(fn = function(x) x^2) >> ls(e) > [1] "fn" "ftrace" "gr" "ifn" "igr" >> e$fn > function(x) x^2 > > ## let's change 'fn': >> e$fn <- function(x) x^4 >> e$fn > function(x) x^4 > > > Note that the environment is always the same, so can be accessed from > anywhere in your code: > >> e2 <- environment(TraceSetup_1) >> e2 > <environment: 0x000000000d1af620> >> identical(e2, e) > [1] TRUE >> > > If you need a new environment every time, a basic setup might be: > > TraceSetup_2 <- local({ > staticVar1 <- NULL > ## other variables here > > function(ifn=0, igr=0, ftrace=FALSE, fn=NA, gr=NA){ > ## force evaluation of the arguments > ifn > igr > ftrace > fn > gr > environment() > } > }) > > There is no need for local() here but usually one needs also some static > variables. > Now every call gives a different environment (but all have the same parent): > > ea <- TraceSetup_2(fn = function(x) x^2 - 2*x + 1) >> ls(ea) > [1] "fn" "ftrace" "gr" "ifn" "igr" >> ea$fn > function(x) x^2 - 2*x + 1 >> >> eb <- TraceSetup_2(fn = function(x) x^2 + 1) >> eb$fn > function(x) x^2 + 1 >> >> ## ea$fn is still the same: >> ea$fn > function(x) x^2 - 2*x + 1 >> > > Obviously, in this case some further arrangements are needed for the > environments to be made available to the external world. > > Hope this helps, > Georgi Boshnakov > > > -----Original Message----- > From: R-package-devel [mailto:r-package-devel-boun...@r-project.org] On > Behalf Of J C Nash > Sent: 28 August 2018 14:18 > To: Fox, John; Richard M. Heiberger > Cc: List r-package-devel > Subject: Re: [R-pkg-devel] Trying to work around missing functionality > > Indeed, it appears that globalVariables must be outside the function. > However, I had quite a bit of > fiddle to get things to work without errors or warnings or notes. While I now > have a package that > does not complain with R CMD check, I am far from satisfied that I can give a > prescription. I had > to remove lines in the rootfinder like > envroot$fn <- fn > that were used to set the function to be used inside my instrumented > function, and instead > call TraceSetup(fn=fn, ...) where a similar statement was given. Why that > worked while the direct > assignment (note, not a <<- one) did not, I do not understand. However, I > will work with this for > a while and try to get a better handle on it. > > Thanks for the pointer. As an old-time programmer from days when you even set > the add table, I'm > still uncomfortable just putting code in a directory and assuming it will be > executed, i.e., the > globals.R file. However, I now have this set to establish the global > structure as follows > >> ## Put in R directory. >> if(getRversion() >= "2.15.1") { utils::globalVariables(c('envroot')) } # Try >> declaring here >> groot<-list(ifn=0, igr=0, ftrace=FALSE, fn=NA, gr=NA, label="none") >> envroot <- list2env(groot) # Note globals in FnTrace > > Then TraceSetup() is > >> TraceSetup <- function(ifn=0, igr=0, ftrace=FALSE, fn=NA, gr=NA){ >> envroot$ifn <- ifn >> envroot$igr <- igr >> envroot$ftrace <- ftrace >> envroot$fn <- fn >> envroot$gr <- gr >> return() >> } > > and it is called at the start of the rootfinder routine. > > Thus I am establishing a global, then (re-)setting values in TraceSetup(), > then > incrementing counters etc. in the instrumented FnTrace() that is the function > for which I find > the root, which calls fn() given by the "user". Messy, but I can now track > progress and measure > effort. > > I'm sure there are cleaner solutions. I suggest offline discussion would be > better until such > options are clearer. > > Thanks again. > > JN > > > > On 2018-08-28 12:01 AM, Fox, John wrote: >> Hi John, >> >> It's possible that I didn’t follow what you did, but it appears as if you >> call globalVariables() *inside* the function. Instead try to do as Richard >> Heiberger suggested and place the call outside of the function, e.g., in a >> source file in the package R directory named globals.R. (Of course, the name >> of the source file containing the command isn’t important.) >> >> I hope this helps, >> John >> >> ----------------------------------------------------------------- >> John Fox >> Professor Emeritus >> McMaster University >> Hamilton, Ontario, Canada >> Web: https://socialsciences.mcmaster.ca/jfox/ >> >> >> >>> -----Original Message----- >>> From: R-package-devel [mailto:r-package-devel-boun...@r-project.org] On >>> Behalf Of J C Nash >>> Sent: Monday, August 27, 2018 8:44 PM >>> To: Richard M. Heiberger <r...@temple.edu> >>> Cc: List r-package-devel <r-package-devel@r-project.org> >>> Subject: Re: [R-pkg-devel] Trying to work around missing functionality >>> >>> Unfortunately, makes things much worse. I'd tried something like this >>> already. >>> >>>> * checking examples ... ERROR >>>> Running examples in ‘rootoned-Ex.R’ failed The error most likely >>>> occurred in: >>>> >>>>> ### Name: rootwrap >>>>> ### Title: zeroin: Find a single root of a function of one variable within >>>>> ### a specified interval. >>>>> ### Aliases: rootwrap >>>>> ### Keywords: root-finding >>>>> >>>>> ### ** Examples >>>>> >>>>> # Dekker example >>>>> # require(rootoned) >>>>> dek <- function(x){ 1/(x-3) - 6 } >>>>> r1 <- rootwrap(dek, ri=c(3.0000001, 6), ftrace=TRUE, >>>>> method="uniroot") >>>> Error in registerNames(names, package, ".__global__", add) : >>>> The namespace for package "rootoned" is locked; no changes in the global >>> variables list may be made. >>>> Calls: rootwrap -> TraceSetup -> <Anonymous> -> registerNames >>>> Execution halted >>> >>> Also had to use utils::globalVariables( ... >>> >>> JN >>> >>> >>> On 2018-08-27 08:40 PM, Richard M. Heiberger wrote: >>>> Does this solve the problem? >>>> >>>> if (getRversion() >= '2.15.1') >>>> globalVariables(c('envroot')) >>>> >>>> I keep this in file R/globals.R >>>> >>>> I learned of this from John Fox's use in Rcmdr. >>>> >>>> On Mon, Aug 27, 2018 at 8:28 PM, J C Nash <profjcn...@gmail.com> >>> wrote: >>>>> In order to track progress of a variety of rootfinding or >>>>> optimization routines that don't report some information I want, I'm >>>>> using the following setup (this one for rootfinding). >>>>> >>>>> TraceSetup <- function(ifn=0, igr=0, ftrace=FALSE, fn=NA, gr=NA){ # >>>>> JN: Define globals here >>>>> groot<-list(ifn=ifn, igr=igr, ftrace=ftrace, fn=fn, gr=gr, >>>>> label="none") >>>>> envroot <<- list2env(groot) # Note globals in FnTrace >>>>> ## This generates a NOTE that >>>>> ## TraceSetup: no visible binding for '<<-' assignment to ‘envroot’ >>>>> ## envroot<-list2env(groot, parent=.GlobalEnv) # Note globals in >>>>> FnTrace - >>> - this does NOT work >>>>> ## utils::globalVariables("envroot") # Try declaring here -- >>>>> causes errors # end globals >>>>> envroot >>>>> } >>>>> >>>>> FnTrace <- function(x,...) { >>>>> # Substitute function to call when rootfinding >>>>> # Evaluate fn(x, ...) >>>>> val <- envroot$fn(x, ...) >>>>> envroot$ifn <- envroot$ifn + 1 # probably more efficient ways >>>>> if (envroot$ftrace) { >>>>> cat("f(",x,")=",val," after ",envroot$ifn," ",envroot$label,"\n") >>>>> } >>>>> val >>>>> } >>>>> >>>>> >>>>> Perhaps there are better ways to do this, but this does seem to work quite >>> well. >>>>> It lets me call a rootfinder with FnTrace and get information on >>>>> evaluations >>> of fn(). >>>>> (There's another gr() routine, suppressed here.) >>>>> >>>>> However, R CMD check gives a NOTE for >>>>> >>>>> TraceSetup: no visible binding for global variable ‘envroot’ >>>>> Undefined global functions or variables: >>>>> envroot >>>>> >>>>> The commented lines in TraceSetup suggest some of the things I've >>>>> tried. Clearly I don't fully comprehend how R is grinding up the >>>>> code, but searches on the net seem to indicate I am far from alone. Does >>> anyone have any suggestion of a clean way to avoid the NOTE? >>>>> >>>>> JN >>>>> >>>>> ______________________________________________ >>>>> R-package-devel@r-project.org mailing list >>>>> https://stat.ethz.ch/mailman/listinfo/r-package-devel >>> >>> ______________________________________________ >>> R-package-devel@r-project.org mailing list >>> https://stat.ethz.ch/mailman/listinfo/r-package-devel > > ______________________________________________ > R-package-devel@r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-package-devel > ______________________________________________ R-package-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-package-devel