add paste & paste0 from R 4.0.1
Closed this issue · 4 comments
from the release notes
CHANGES IN R 4.0.1
NEW FEATURES
- paste() and paste0() gain a new optional argument recycle0. When set to true, zero-length arguments are recycled leading to character(0) after the sep-concatenation, i.e., to the empty string "" if collapse is a string and to the zero-length value character(0) when collapse = NULL.
A package whose code uses this should depend on R (>= 4.0.1).
TBH, I have a hard time understanding the intended behavior after reading both news and man page.
Understandably. There has been a very lengthy discussion about how it should behave r-devel.
As previously, paste0
is just paste
currying the sep
argument to ""
:
paste0 <- function(..., collapse = NULL, recycle0 = FALSE) paste(..., sep = "", collapse = collapse, recycle0 = recycle0)
Only difference is that it now also forwards the recycle0
argument.
paste
with recycle0 = FALSE
(the default) behaves as previously.
To understand the new behavior for recycle0 = TRUE
it helps to think of paste as two different functions by considering the following identity:
paste <==> function(..., sep = " ", collapse = NULL, recycle0 = FALSE)
paste(paste(..., sep = sep, recycle0 = recycle0), collapse = collapse)
Only the inner part of paste
, the one that concatenates that performs an element wise concatenation, is affected by the new recycle0
argument. Previously and now with recycle0 = FALSE
, paste
would not recycle zero-length arguments but replace them by rep("", max(sapply(list(...), length)))
. This means that paste0("Hello", character(0), "!")
would (somewhat unexpectedly) yield "Hello !"
. With the new recycle0 = TRUE
, paste
recycles zero-length arguments just like e.g. +
does for integer
s:
paste0("Hello", character(0), "!", recycle0 = TRUE)
yields character(0)
, just like 1L+integer(0)==integer(0)
or (1:3)+integer(0)==integer(0)
.
you could implement the new paste like this (and paste0 accordingly):
paste <- function(..., sep = " ", collapse = NULL, recycle0 = FALSE) {
if(recycle0 && any(vapply(list(...), length, FUN.VALUE = integer(1))==0)) {
paste(sep = sep, collapse = collapse) # for argument checking
if (is.null(collapse)) character(0) else ""
} else base::paste(..., sep = sep, collapse = collapse)
}
In words: if recycle0
is set to true & there are zero-length arguments paste
returns the empty string "" if collapse is a string and to the zero-length value character(0) when collapse = NULL.
See also my SO question for an application.
This would be indeed nice to have.
Great, thank you!