[Rd] Bug in stats:::`[.formula`: (~ NULL)[2] gives Error ... missing value where TRUE/FALSE needed
Henrik Bengtsson
henr|k@bengt@@on @end|ng |rom gm@||@com
Fri Aug 14 23:05:04 CEST 2020
Hi, it looks like:
> stats:::`[.formula`
function (x, i)
{
ans <- NextMethod("[")
if (length(ans) == 0L || as.character(ans[[1L]])[1L] == "~") {
class(ans) <- "formula"
environment(ans) <- environment(x)
}
ans
}
<bytecode: 0x556688d87cc0>
<environment: namespace:stats>
doesn't like to extract NULL components on either the LHS or RHS. For
example, with
> (~ NULL)[2]
Error in if (length(ans) == 0L || as.character(ans[[1L]])[1L] == "~") { :
missing value where TRUE/FALSE needed
this despite:
> str(as.list(~ NULL))
List of 2
$ : symbol ~
$ : NULL
- attr(*, "class")= chr "formula"
- attr(*, ".Environment")=<environment: R_GlobalEnv>
> length(~ NULL)
[1] 2
> (~ NULL)[[2]]
NULL
Other examples are:
> (NULL ~ .)[2]
Error in if (length(ans) == 0L || as.character(ans[[1L]])[1L] == "~") { :
missing value where TRUE/FALSE needed
> (NULL ~ NULL)[3]
Error in if (length(ans) == 0L || as.character(ans[[1L]])[1L] == "~") { :
missing value where TRUE/FALSE needed
TROUBLESHOOTING:
The reason is that ans[[1L]] becomes NULL;
> trace(stats:::`[.formula`, tracer = quote(utils::str(as.list(ans))), at = 3L)
Tracing function "[.formula" in package "stats (not-exported)"
[1] "[.formula"
> (~ NULL)[2]
Tracing `[.formula`((~NULL), 2) step 3
List of 1
$ : NULL
Error in if (length(ans) == 0L || as.character(ans[[1L]])[1L] == "~") { :
missing value where TRUE/FALSE needed
which causes 'as.character(ans[[1L]])[1L] == "~"' to resolve to NA.
PATCH:
A minimal backward compatible fix would be:
`[.formula` <- function(x,i) {
ans <- NextMethod("[")
## as.character gives a vector.
if(length(ans) == 0L || (is.null(ans[[1L]]) && i <= length(x)) ||
as.character(ans[[1L]])[1L] == "~") {
class(ans) <- "formula"
environment(ans) <- environment(x)
}
ans
}
A better fix would probably be to also detect out of range as in:
`[.formula` <- function(x,i) {
if (i > length(x))
stop(gettext("index out of range"))
ans <- NextMethod("[")
## as.character gives a vector.
if(length(ans) == 0L || is.null(ans[[1L]]) ||
as.character(ans[[1L]])[1L] == "~") {
class(ans) <- "formula"
environment(ans) <- environment(x)
}
ans
}
/Henrik
More information about the R-devel
mailing list