[Rd] Conventions: Use of globals and main functions

Duncan Murdoch murdoch@dunc@n @end|ng |rom gm@||@com
Mon Aug 26 20:19:36 CEST 2019

On 26/08/2019 1:58 p.m., William Dunlap wrote:
> Duncan Murdoch wrote:
>  > Scripts are for throwaways, not for anything worth keeping.
> I totally agree and have a tangentially relevant question about the <<- 
> operator.  Currently 'name <<- value' means to look up the environment 
> stack until you find 'name'  and (a) if you find 'name' in some frame 
> bind it to a new value in that frame and (b) if you do not find it make 
> a new entry for it in .GlobalEnv.
> Should R deprecate the second part of that and give an error if 'name' 
> is not already present in the environment stack?  This would catch 
> misspelling errors in functions that collect results from recursive 
> calls.  E.g.,

I like that suggestion.  Package tests have been complaining about 
packages writing to .GlobalEnv for a while now, so there probably aren't 
many instances of b) in CRAN packages; that change might be relatively 

Duncan Murdoch

> collectStrings <- function(list) {
>      strings <- character() # to be populated by .collect
>      .collect <- function(x) {
>          if (is.list(x)) {
>              lapply(x, .collect)
>          } else if (is.character(x)) {
>              strings <<- c(strings, x)
>          }
>          misspelledStrings <<- c(strings, names(x)) # oops, would like 
> to be told about this error
>          NULL
>      }
>      .collect(list)
>      strings
> }
> This gives the incorrect:
>  > collectStrings(list(i="One", ii=list(a=1, b="Two")))
> [1] "One" "Two"
>  > misspelledStrings
> [1] "One" "Two" "i"   "ii"
> instead of what we would get if 'misspelledStrings' were 'strings'.
>  > collectStrings(list(i="One", ii=list(a=1, b="Two")))
> [1] "One" "Two" "a"   "b"   "i"   "ii"
> If someone really wanted to assign into .GlobalEnv the assign() function 
> is available.
> In S '<<-' only had meaning (b) and R added meaning (a).  Perhaps it is 
> time to drop meaning (b).  We could start by triggering a warning about 
> it if some environment variable were set, as is being done for 
> non-scalar && and ||.
> Bill Dunlap
> TIBCO Software
> wdunlap tibco.com <http://tibco.com>
> On Sun, Aug 25, 2019 at 5:09 PM Duncan Murdoch <murdoch.duncan using gmail.com 
> <mailto:murdoch.duncan using gmail.com>> wrote:
>     On 25/08/2019 7:09 p.m., Cyclic Group Z_1 wrote:
>      >
>      >
>      > This is a fair point; structuring functions into packages is
>     probably ultimately the gold standard for code organization in R.
>     However, lexical scoping in R is really not much different than in
>     other languages, such as Python, in which use of main functions and
>     defining other named functions outside of main are encouraged. For
>     example, in Scheme, from which R derives its scoping rules, the
>     community generally organizes code with almost exclusively functions
>     and few non-function global variables at top level. The common use
>     of globals in R seems to be mostly a consequence of historical
>     interactive use and, relatedly, an inherited practice from S.
>      >
>      > It is true, though, that since anonymous functions (such as in
>     lapply) play a large part in idiomatic R code, as you put it,
>     "[l]exical scoping means that all of the problems of global
>     variables are available to writers who use main()." Nevertheless,
>     using a main function with other functions defined outside it seems
>     like a good quick alternative that offers similar advantages to
>     making a package when functions are tightly coupled to the script
>     and the project may not be large or generalizable enough to warrant
>     making a package.
>      >
>     I think the idea that making a package is too hard is just wrong.
>     Packages in R have lots of requirements, but nowadays there are tools
>     that make them easy.  Eleven years ago at UseR in Dortmund I wrote a
>     package during a 45 minute presentation, and things are much easier now.
>     If you make a complex project without putting most of the code into a
>     package, you don't have something that you will be able to modify in a
>     year or two, because you won't have proper documentation.
>     Scripts are for throwaways, not for anything worth keeping.
>     Duncan Murdoch
>     ______________________________________________
>     R-devel using r-project.org <mailto:R-devel using r-project.org> mailing list
>     https://stat.ethz.ch/mailman/listinfo/r-devel

More information about the R-devel mailing list