[Rd] R (development) changes in arith, logic, relop with (0-extent) arrays
Martin Maechler
maechler at stat.math.ethz.ch
Tue Sep 6 22:26:31 CEST 2016
Yesterday, changes to R's development version were committed, relating
to arithmetic, logic ('&' and '|') and
comparison/relational ('<', '==') binary operators
which in NEWS are described as
SIGNIFICANT USER-VISIBLE CHANGES:
[.............]
• Arithmetic, logic (‘&’, ‘|’) and comparison (aka
‘relational’, e.g., ‘<’, ‘==’) operations with arrays now
behave consistently, notably for arrays of length zero.
Arithmetic between length-1 arrays and longer non-arrays had
silently dropped the array attributes and recycled. This
now gives a warning and will signal an error in the future,
as it has always for logic and comparison operations in
these cases (e.g., compare ‘matrix(1,1) + 2:3’ and
‘matrix(1,1) < 2:3’).
As the above "visually suggests" one could think of the changes
falling mainly two groups,
1) <0-extent array> (op) <non-array>
2) <1-extent array> (arith) <non-array of length != 1>
These changes are partly non-back compatible and may break
existing code. We believe that the internal consistency gained
from the changes is worth the few places with problems.
We expect some package maintainers (10-20, or even more?) need
to adapt their code.
Case '2)' above mainly results in a new warning, e.g.,
> matrix(1,1) + 1:2
[1] 2 3
Warning message:
In matrix(1, 1) + 1:2 :
dropping dim() of array of length one. Will become ERROR
>
whereas '1)' gives errors in cases the result silently was a
vector of length zero, or also keeps array (dim & dimnames) in
cases these were silently dropped.
The following is a "heavily" commented R script showing (all ?)
the important cases with changes :
----------------------------------------------------------------------------
(m <- cbind(a=1[0], b=2[0]))
Lm <- m; storage.mode(Lm) <- "logical"
Im <- m; storage.mode(Im) <- "integer"
## 1. -------------------------
try( m & NULL ) # in R <= 3.3.x :
## Error in m & NULL :
## operations are possible only for numeric, logical or complex types
##
## gives 'Lm' in R >= 3.4.0
## 2. -------------------------
m + 2:3 ## gave numeric(0), now remains matrix identical to m
Im + 2:3 ## gave integer(0), now remains matrix identical to Im (integer)
m > 1 ## gave logical(0), now remains matrix identical to Lm (logical)
m > 0.1[0] ## ditto
m > NULL ## ditto
## 3. -------------------------
mm <- m[,c(1:2,2:1,2)]
try( m == mm ) ## now gives error "non-conformable arrays",
## but gave logical(0) in R <= 3.3.x
## 4. -------------------------
str( Im + NULL) ## gave "num", now gives "int"
## 5. -------------------------
## special case for arithmetic w/ length-1 array
(m1 <- matrix(1,1,1, dimnames=list("Ro","col")))
(m2 <- matrix(1,2,1, dimnames=list(c("A","B"),"col")))
m1 + 1:2 # -> 2:3 but now with warning to "become ERROR"
tools::assertError(m1 & 1:2)# ERR: dims [product 1] do not match the length of object [2]
tools::assertError(m1 < 1:2)# ERR: (ditto)
##
## non-0-length arrays combined with {NULL or double() or ...} *fail*
### Length-1 arrays: Arithmetic with |vectors| > 1 treated array as scalar
m1 + NULL # gave numeric(0) in R <= 3.3.x --- still, *but* w/ warning to "be ERROR"
try(m1 > NULL) # gave logical(0) in R <= 3.3.x --- an *error* now in R >= 3.4.0
tools::assertError(m1 & NULL) # gave and gives error
tools::assertError(m1 | double())# ditto
## m2 was slightly different:
tools::assertError(m2 + NULL)
tools::assertError(m2 & NULL)
try(m2 == NULL) ## was logical(0) in R <= 3.3.x; now error as above!
----------------------------------------------------------------------------
Note that in R's own 'nls' sources, there was one case of
situation '2)' above, i.e. a 1x1-matrix was used as a "scalar".
In such cases, you should explicitly coerce it to a vector,
either ("self-explainingly") by as.vector(.), or as I did in
the nls case by c(.) : The latter is much less
self-explaining, but nicer to read in mathematical formulae, and
currently also more efficient because it is a .Primitive.
Please use R-devel with your code, and let us know if you see
effects that seem adverse.
In some case where R-devel now gives an error but did not
previously, we could contemplate giving another "warning
.... 'to become ERROR'" if there was too much breakage, though
I don't expect that.
For the R Core Team,
Martin Maechler,
ETH Zurich
More information about the R-devel
mailing list