0
> 1:3
[1] 1 2 3
> c(1:3)
[1] 1 2 3
> test=1:3
> test
[1] 1 2 3
> str(test)
 int [1:3] 1 2 3

No surprises so far.

> bb <- c(tst=1:3)
> bb

Expected:

int [1:3] 1 2 3

or

[1] 1 2 3

.

> str(bb)

Expected:

Named int [1:3] 1 2 3
 - attr(*, "names")= chr [1] "tst" 

Actual:

> bb
tst1 tst2 tst3 
   1    2    3

> str(bb)
 Named int [1:3] 1 2 3
 - attr(*, "names")= chr [1:3] "tst1" "tst2" "tst3"

Where did those names come from?

I mean, they are plausible enough names, but I don't see anything that could produce them.

I've looked at help for c, :, =, at the names() function, and even at (. I've looked at the code for : and c, so see if I might have overwritten them somehow, and at tst in case it was some weird function that doesn't need a parenthesis. I've closed R and restarted it with an empty workspace.

I'm baffled.

NEW INFORMATION:

Well, it looks to me like the answer is probably in this code snippet, and I'm prepared to bet that the creation of three names has something to do with the "recurse" argument to NewExtractNames, but I don't know enough c to understand exactly what is happening. But I thought I would put the code here to make it easier for someone with deeper knowledge (@hrbrmstr, maybe?) to answer if they are so moved.

  if (data.ans_nnames && data.ans_length > 0) {
    PROTECT(data.ans_names = allocVector(STRSXP, data.ans_length));
    data.ans_nnames = 0;
    while (args != R_NilValue) {
        nameData.seqno = 0;
        nameData.firstpos = 0;
        nameData.count = 0;
        NewExtractNames(CAR(args), R_NilValue, TAG(args), recurse, &data, &nameData);
        args = CDR(args);
    }
    setAttrib(ans, R_NamesSymbol, data.ans_names);
    UNPROTECT(1);
    }
andrewH
  • 2,281
  • 2
  • 22
  • 32
  • Interesting. Much different from the result produced by `setNames(1:3, "tst")` or using `names<-` after creating `bb`. Looks like unique names are made based on the element's position in the vector. `c(tst = 4:6)` led me to that. The same names are produced there even though the values are different. `c()` is a primitive, so this answer will come from digging into the C code. – Rich Scriven Aug 28 '16 at 02:26
  • `do_c_dflt` in `src/main/bind.c` has your answer. – hrbrmstr Aug 28 '16 at 03:23
  • 1
    Since `bb` is a vector of `length == 3`, then its "names" cannot be of different length as in your expected case. So, even in that case, a vector of "names" like `c("tst", NA, NA)` would seem more suitable. In case of naming, think of `c(...)` as `unlist(list(...))` since they both seem to use the same approach in making "names" -- `unlist(list(tst = 1:3))`. Perhaps with an example like `c(nm2 = c(nm1 = 1:2))` `c`'s naming would seem more reasonable. See the [undocumented "use.names" argument](http://stackoverflow.com/questions/24815572/why-does-function-c-accept-an-undocumented-argument), too – alexis_laz Aug 28 '16 at 15:08
  • @alexis_laz What I was actually expecting, albeit not with a very good reason, was data.frame()-like behavior. I thought I would produce a named object inside of c() and get out a list of one named vector - not a vector with a names attribute, a vector with a name. – andrewH Aug 28 '16 at 21:20
  • 1
    @DirtySockSniffer Fascinating. Works for c(tst = letters[1:3]) and c(prefix = list(1, 2, 3)) as well. I am starting to believe that this is a useful and intentional feature that someone just forgot to document - a sort of quicknames feature for vectors and lists. – andrewH Aug 28 '16 at 22:21

0 Answers0