The c() function is used in R to combine values into a vector a list:
So what, this is basic knowledge, why should I care? Well, somewhere in the middle of the documentation, you'll find the sentence:
"c is sometimes used for its side effect of removing attributes except names, for example to turn an array into a vector".
Let's see what is actually meant by this.
x <- "man" names(x) <- "Jack" str(x) # Named chr "man" #- attr(*, "names")= chr "Jack" y <- "woman" names(y) <- "Mary" str(y) # Named chr "woman" #- attr(*, "names")= chr "Mary" z <- c(x, y) str(z) # Named chr [1:2] "man" "woman" # - attr(*, "names")= chr [1:2] "Jack" "Mary"
But what happens if we set some other attributes?
x <- 42 attr(x = x, which = "value") <- "parameter1" str(x) # num 42 #- attr(*, "value")= chr "parameter1" y <- 100 attr(x = y, which = "value") <- "parameter2" str(y) # num 100 #- attr(*, "value")= chr "parameter2" z <- c(x, y) str(z) # num [1:2] 42 100
The "value" attribute is lost. Of course you can set the attributes like this:
attr(x = z, which = "value") <- c("parameter1", "parameter2") str(z) # num [1:2] 42 100 #- attr(*, "value")= chr [1:2] "parameter1" "parameter2"
but I think that in general, writing functions with side effects is not advisable - or at least the function name should describe what it actually does.
I bumped into this side effect of the c() function a while ago. I had a function which was supposed to return a parameter value from a data base, with parameter name as argument of the function. In most of the use cases, only one parameter was asked for. However, at some point there were also multiple parameters.
The question was: how to return the values associated with the corresponding parameter names? The solution was to return a vector of values, with parameter names as attributes. While the solution seemed straightforward, I had to learn the hard way that c() does not keep other attributes aside "names". Consider yourself warned.
Did you know that in R the only object that cannot have attributes is the NULL object?
x <- NULL attr(x = x, which = "color") <- "black" # Error in attr(x = x, which = "color") <- "black" : # attempt to set an attribute on NULL
Make a promise. Show up. Do the work. Repeat.