From m@ech|er @end|ng |rom @t@t@m@th@ethz@ch  Wed Sep 18 11:29:20 2019
From: m@ech|er @end|ng |rom @t@t@m@th@ethz@ch (Martin Maechler)
Date: Wed, 18 Sep 2019 11:29:20 +0200
Subject: [Rd] '==' operator: inconsistency in data.frame(...) == NULL
In-Reply-To: <23937.60510.182530.176708@stat.math.ethz.ch>
References: <9075d086-7945-b759-f311-765d626b7a61@mpiib-berlin.mpg.de>
 <23928.43189.410927.15494@stat.math.ethz.ch>
 <c21fa68d-00da-dcc1-6390-dce52c889748@mpiib-berlin.mpg.de>
 <f144303d-0fa6-7827-bca3-2587a43c3484@mpiib-berlin.mpg.de>
 <1bbabc36-43c8-aad6-4a08-b310d13c8938@mpiib-berlin.mpg.de>
 <94e5fbbe-6f03-9b69-8abf-ebeced33a016@mpiib-berlin.mpg.de>
 <23937.60510.182530.176708@stat.math.ethz.ch>
Message-ID: <23937.63728.859845.525356@stat.math.ethz.ch>

>>>>> Martin Maechler 
>>>>>     on Wed, 18 Sep 2019 10:35:42 +0200 writes:

  >>>>> Hilmar Berger 
  >>>>>     on Sat, 14 Sep 2019 13:31:27 +0200 writes:

       >> Dear all,
       >> I did some more tests regarding the == operator in Ops.data.frame (see 
       >> below).? All tests done in R 3.6.1 (x86_64-w64-mingw32).

       >> I find that errors are thrown also when comparing a zero length 
       >> data.frame to atomic objects with length>0 which should be a valid case 
       >> according to the documentation. This can be traced to a check in the 
       >> last line of Ops.data.frame which tests for the presence of an empty 
       >> result value (i.e. list() ) but does not handle a list of empty values 
       >> (i.e. list(logical(0))) which in fact is generated in those cases. 

       >> There  is a simple fix (see also below).

    > I'm pretty sure what you write above is wrong:  For some reason
    > you must have changed more in your own version of Ops.data.frame :

    > Because there's a line

    > value <- unlist(value, ...)

    > there, value is *not*  list(logical(0)) there, but rather  logical(0)
    > and then indeed, your proposed line change (at the end of Ops.data.frame)
    > has no effect for the examples you give.

On the other hand, there *is* a simple "fix" at the end of
Ops.data.frame()  which makes all your examples "work" (i.e. not
give an error), namely

----------------------------------------------------------------------

@@ -1685,7 +1684,7 @@
     else { ## 'Logic' ("&","|")  and  'Compare' ("==",">","<","!=","<=",">=") :
 	value <- unlist(value, recursive = FALSE, use.names = FALSE)
 	matrix(if(is.null(value)) logical() else value,
-	       nrow = nr, dimnames = list(rn,cn))
+	       nrow = nr, ncol = length(cn), dimnames = list(rn,cn))
     }

----------------------------------------------------------------------

i.e., explicitly specifying 'ncol' compatibly with the column names.
However, I guess that this change would *not* signal errors
where it *should* and so am *not* (yet?) proposing to "do" it.

Another remark, on  S4  which you've raised several times:
As you may know that the 'Matrix' package (part of every
"regular" R installation) uses S4 "everywhere" and it does
define many methods for its Matrix classes, all in source file  Matrix/R/Ops.R
the development version (in svn / subversion) being online on R-forge here:

  https://r-forge.r-project.org/scm/viewvc.php/pkg/Matrix/R/Ops.R?view=markup&root=matrix

and "of course", there we define S4 group methods for Ops all
the time, and (almost) never S3 ones...
[[but I hope you don't want to start combining data frames
 with Matrix package matrices, now !]]

Martin Maechler
ETH Zurich  and  R Core Team



[Rd] '==' operator: inconsistency in data.frame(...) == NULL
Martin Maechler