[Rd] all.equal() applied to function closures -- now committed

Martin Maechler m@ech|er @end|ng |rom @t@t@m@th@ethz@ch
Fri Dec 4 12:40:33 CET 2020

>>>>> Martin Maechler 
>>>>>     on Thu, 3 Dec 2020 18:29:58 +0100 writes:

>>>>> Martin Maechler 
>>>>>     on Tue, 1 Dec 2020 10:31:36 +0100 writes:

>>>>> Bill Dunlap 
>>>>>     on Mon, 30 Nov 2020 13:41:54 -0800 writes:

    >>> To make the comparison more complete,
    >>> all.equal.environment could compare the parents of the
    >>> target and current environments.  That would have to be
    >>> recursive but could stop at the first 'top level
    >>> environment' (the global, empty, or a package-related
    >>> environment generally) and use identical there.  E.g.,

    >>> > f1 <- function(x) (function(){ expx <- exp(x) ; function(y) y + expx})()
    >>> > all.equal(f1(2), f1(3))
    >>> [1] "Environments: Component “expx”: Mean relative difference: 1.718282"
    >>> [2] "Environments: <parent.env> Component “x”: Mean relative difference:
    >>> 0.5"

    >>> This is from the following, where I avoided putting the existing
    >>> non-recursive all.equal.environment into the body of this one.

    > [[.........]]

    >> Thank you, Duncan and Bill (and Kevin for bringing up the
    >> topic).

    >> I agree  all.equal() should work better with functions,

    >> and I think probably it would make sense to define  all.equal.function()
    >> rather than put this into all.equal.default()

    >> However, it's not quite clear if it is always desirable to check the
    >> environments as well notably as that *is* done recursively.

    > A small  "work in progress" update (because I've been advancing slowly only):

    > I'm currently testing 'make check-all' after

    > 1) adding all.equal.function() method,
    > 2) not changing  all.equal.environment() yet
    > 3) but adapting all.equal.default() to give a deprecating warning
    > when called with a function

    > all.equal.function <- function(target, current, check.environments = TRUE, ...)
    > {
    > }

    > It's amazing that this breaks our own checks in several places,
    > which I'm chasing slowly (being busy with teaching related
    > duties, etc).
    > I did have the correct gut feeling to have 'check.environments'
    > being an optional argument, because indeed there are cases (in
    > our own regression tests) where we now needed to change the
    > checks to use   check.environments=FALSE .

    > My plan is to finish the   all.equal.function()  functionality /
    > modify "base R" coded (or, for now, rather the testing code)
    > where needed, and then *commit* that to R-devel.

I've done that now:
r79555 | maechler | 2020-12-04 12:13:06 +0100 (Fri, 04 Dec 2020) | 1 line
Changed paths:
   M doc/NEWS.Rd
   M src/library/base/R/all.equal.R
   M src/library/base/R/zzz.R
   M src/library/base/man/all.equal.Rd
   M src/library/base/man/dput.Rd
   M src/library/stats/tests/nls.R
   M src/library/stats/tests/nls.Rout.save
   M tests/eval-etc-2.Rout.save
   M tests/eval-etc.Rout.save
   M tests/eval-fns.R
   M tests/reg-tests-1d.R

new all.equal.function() checks environment(.)

Note the seven extra files needed to be changed


where in all cases I needed to add an explicit
', check.environments = FALSE' to an existing  stopifnot(all.equal(..))

Consequently, I expect some  "carnage" in checks of existing  CRAN / BioC 
(and github, etc but that does not count) packages.

The NEWS entry (in 'NEW FEATURES') mentions an important case :

    • all.equal(f, g) for functions now by default also compares their
      environment(.)s, notably via new all.equal method for class
      function.  Comparison of nls() fits, e.g., may now need
      all.equal(m1, m2, check.environments=FALSE).

So if you are a package maintainer observing that all.equal() --
or its corresponding 'testthat' obfuscation -- signals errors
"suddenly" (and only in R-devel), it's that you need to add
'check.environments=FALSE' there.

The good news is that this works also in existing (and previous)
versions of R :

  > all.equal(lm,lm, check.environments=FALSE)
  [1] TRUE

thanks to the "..."  _feature_ of typically just silently swallowing
everything that's not understood.  (yes: _feature_ is tongue in cheek).


    > After that we should come back to improve or even re-write
    > all.equal.environment()  when needed.

More information about the R-devel mailing list