[Rd] Should c(..., recursive = TRUE) and unlist(x, recursive = TRUE) recurse into expression vectors?

Mikael Jagan j@g@nmn2 @end|ng |rom gm@||@com
Sat Apr 27 16:53:12 CEST 2024


Reading the body of function 'AnswerType' in bind.c, called from 'do_c'
and 'do_unlist', I notice that EXPRSXP and VECSXP are handled identically
in the  recurse = TRUE  case.

A corollary is that  c(recursive = TRUE)  and  unlist(recursive = TRUE)
treat expression vectors like  expression(a, b)  as lists of symbols and
calls.  And since they treat symbols and calls as lists of length 1, we
see:

 > x <- expression(a, b); y <- expression(c, d)
 > c(x, y)
expression(a, b, c, d)
 > c(x, y, recursive = TRUE)
[[1]]
a

[[2]]
b

[[3]]
c

[[4]]
d

My expectation based on the documentation in help("c") and help("unlist")
is that those functions would recurse into lists and pairlists, but _not_
into expression vectors.

     recursive: logical.  If 'recursive = TRUE', the function recursively
               descends through lists (and pairlists) combining all their
               elements into a vector.

     recursive: logical.  Should unlisting be applied to list components of
               'x'?

My feeling is that either:

(1) the behaviour should change, so that both calls to 'c' above give
     the result of type "expression".
(2) the documentation should change to say that expression vectors are
     handled as lists in the recursive case.

Option (2) won't break anything but is a bit awkward because it means
that a type "higher" in the documented hierarchy (... < list < expression)
is coerced to a lower type.

I'll add here that, confusingly, help("expression") says: "an object of
mode 'expression' is a list".  I understand the author's intent (lists and
expression vectors differ only in the 'type' field of the SEXP header) but
I wonder if substituting "list" with "generic vector" there would cause
less confusion ... ?

Mikael



More information about the R-devel mailing list