From murdoch@dunc@n @end|ng |rom gm@||@com  Mon Aug 26 20:19:36 2019
From: murdoch@dunc@n @end|ng |rom gm@||@com (Duncan Murdoch)
Date: Mon, 26 Aug 2019 14:19:36 -0400
Subject: [Rd] Conventions: Use of globals and main functions
In-Reply-To: <CAF8bMcaU2ycRd7YA1ziZeoVyZ24uY1fTmV9131pbp2p3uM_qVQ@mail.gmail.com>
References: <1118624909.2128031.1566706119596.ref@mail.yahoo.com>
 <1118624909.2128031.1566706119596@mail.yahoo.com>
 <551feaef-9cf1-91d5-ff4a-0eeb36328bab@gmail.com>
 <1278224074.2337376.1566774597756@mail.yahoo.com>
 <739a44fe-4fd4-ee75-cf93-ea32d8760de7@gmail.com>
 <CAF8bMcaU2ycRd7YA1ziZeoVyZ24uY1fTmV9131pbp2p3uM_qVQ@mail.gmail.com>
Message-ID: <ab5d1ccd-b971-4403-e328-db9bb3b23ec5@gmail.com>

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 
painless.

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 at gmail.com 
> <mailto:murdoch.duncan at 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 at r-project.org <mailto:R-devel at r-project.org> mailing list
>     https://stat.ethz.ch/mailman/listinfo/r-devel
>



[Rd] Conventions: Use of globals and main functions
Duncan Murdoch