Hacer un operador de concatenación de cadenas en R

Me preguntaba cómo se podría escribir un operador de concatenación de cadenas en R, algo así como || en SAS, + en Java / C # o & en Visual Basic.

La manera más fácil sería crear un operador especial usando%, como

`%+%` <- function(a, b) paste(a, b, sep="") 

pero esto lleva a muchos % feos en el código.

Noté que + se define en el grupo Ops, y puedes escribir los métodos S4 para ese grupo, así que tal vez algo así sería el camino a seguir. Sin embargo, no tengo ninguna experiencia con las características del lenguaje S4 en absoluto. ¿Cómo modificaría la función anterior para usar S4?

Como han mencionado otros, no puede anular el método sellado S4 “+”. Sin embargo, no necesita definir una nueva clase para definir una función de adición para cadenas; esto no es ideal ya que te obliga a convertir la clase de cadenas y por lo tanto a un código más feo. En cambio, uno simplemente puede sobrescribir la función “+”:

 "+" = function(x,y) { if(is.character(x) || is.character(y)) { return(paste(x , y, sep="")) } else { .Primitive("+")(x,y) } } 

Entonces, todo lo siguiente debería funcionar como se espera:

 1 + 4 1:10 + 4 "Help" + "Me" 

Esta solución se parece un poco a un truco, ya que ya no se usan métodos formales, pero es la única manera de obtener el comportamiento exacto que se desea.

También puedes usar clases S3 para esto:

 String <- function(x) { class(x) <- c("String", class(x)) x } "+.String" <- function(x,...) { x <- paste(x, paste(..., sep="", collapse=""), sep="", collapse="") String(x) } print.String <- function(x, ...) cat(x) x <- "The quick brown " y <- "fox jumped over " z <- "the lazy dog" String(x) + y + z 

Voy a probar esto (relativamente más solución S3 limpia)

 `+` <- function (e1, e2) UseMethod("+") `+.default` <- function (e1, e2) .Primitive("+")(e1, e2) `+.character` <- function(e1, e2) if(length(e1) == length(e2)) { paste(e1, e2, sep = '') } else stop('String Vectors of Different Lengths') 

El código anterior cambiará + a un genérico, y establecerá +.default en el original + , luego agregará el nuevo método +.character a +

Si R cumpliera estrictamente con S4, lo siguiente hubiera sido suficiente:

 setMethod("+", signature(e1 = "character", e2 = "character"), function (e1, e2) { paste(e1, e2, sep = "") }) 

Pero esto da un error de que el método está sellado: (.. Esperemos que esto cambie en las versiones de características de R.

Lo mejor que puede hacer es definir una nueva clase “cadena” que se comportaría exactamente como clase de “carácter”:

 setClass("string", contains="character") string <- function(obj) new("string", as.character(obj)) 

y define el método más general que R permite:

 setMethod("+", signature(e1 = "character", e2 = "ANY"), function (e1, e2) string(paste(e1, as.character(e2), sep = ""))) 

ahora intenta:

 tt <- string(44444) tt #An object of class "string" #[1] "44444" tt + 3434 #[1] "444443434" "sfds" + tt #[1] "sfds44444" tt + tt #[1] "4444444444" 343 + tt #Error in 343 + tt : non-numeric argument to binary operator "sdfs" + tt + "dfsd" #An object of class "string" #[1] "sdfs44444dfsd" 

Te has dado la respuesta correcta: todo en R es una función, y no puedes definir nuevos operadores. Entonces %+% es tan bueno como se pone.