Reputation: 6780
I am trying to write an rbind
method for a particular class. Here's a simple example where it doesn't work (at least for me):
rbind.character <- function(...) {
do.call("paste", list(...))
}
After entering this function, I seemingly can confirm that it is a valid method that R knows about:
> methods("rbind")
[1] rbind.character rbind.data.frame rbind.rootogram* rbind.zoo*
see '?methods' for accessing help and source code
However, it is not recognized if I try to use it:
> rbind("abc", "xyz")
[,1]
[1,] "abc"
[2,] "xyz"
> #### compared with ####
> rbind.character("abc", "xyz")
[1] "abc xyz"
The help page says that dispatch is performed internally as follows:
With rbind("abc", "xyz")
, I believe all these criteria are satisfied. What gives, and how can I fix it?
Upvotes: 14
Views: 376
Reputation: 132706
attributes("abc")
#NULL
A character
vector doesn't have a class attribute. I don't think a method can be dispatched by rbind
for the implicit classes.
Upvotes: 9
Reputation: 37045
rbind
is not a standard S3 function, so you cannot "intercept" it for character
.
Luckily, you can override the default implementation. Try:
rbind.character <- function(...) {
print("hello from rbind.character")
}
rbind <- function(...) {
args <- list(...)
if (all(vapply(args, is.character, logical(1)))) {
rbind.character(...)
} else {
base::rbind(...)
}
}
Basically, we check if the arguments are all characters. If so, we call our character function. If not, we call the default implementation.
Upvotes: 1
Reputation: 20329
A workaround would be to define your own class:
b <- "abc"
class(b) <- "mycharacter"
rbind.mycharacter <- function(...) {
do.call("paste", list(...))
}
rbind(b, b)
# [1] "abc abc"
The reason why it does not work with character
was nicely explained by Roland in his comment.
Upvotes: 3