Search code examples
rvector

issue creating a named vector with paste


This seems a rudimental question but I can't find an explanation on SO.

I can name a vector like so:

values = c("lab1" = "my_lab1", 
           "lab2" = "my_lab2")
values
#      lab1      lab2 
# "my_lab1" "my_lab2" 

I can create the same vector by using paste0 to create an element like so:

values = c("lab1" = "my_lab1", 
           "lab2" = paste0("my_lab", "2"))
values
#      lab1      lab2 
# "my_lab1" "my_lab2"

But when you try to create the name with paste0, it causes an error:

values = c("lab1" = "my_lab1", 
           paste0("lab", "2") = "my_lab2")
# Error: unexpected '=' in:
# "values = c("lab1" = "my_lab1", 
#            paste0("lab", "2") ="

Why is this? Considering that the following is true:

identical("lab2", paste0("lab", "2"))
[1] TRUE

A solution is to use setNames but I am interested in why the above is an issue:

setNames(c("my_lab1", "my_lab2"), c("lab1", paste0("lab", "2")))
#      lab1      lab2 
# "my_lab1" "my_lab2"

I can't see any mention to this in the vector section of Advanced R.

Thanks


Solution

  • The problem is that named parameters are simply never evaluated. They are assumed to be literal values. Consider the case of

    foo <- function(a=5, x=10) {a+x}
    

    And then you did

    x <- "a"
    foo(x = 2)
    foo(paste(x) = 2) # error
    

    If you expect the "x" to be evaluated, it can get very confusing what actually is supposed to run. The R parser does not expect to see expressions as parameter names. The grammar is defined in the R source code There is also a reference to this fact in the R Language Definition where it states

    Each argument can be tagged (tag=expr), or just be a simple expression. It can also be empty or it can be one of the special tokens ..., ..2, etc. [...] A tag can be an identifier or a text string.

    which does imply the tag cannot be an expression itself.

    In the example I used foo as a function, but c is also just a function. And while it doesn't' have explicit named parameters, it does follow all the same rules for other functions about parameter names.

    In the tidyverse/rlang world, they defined a new function := which allows you to use names for parameters

    rlang::list2("lab1" = "my_lab1", 
                   !!paste0("lab", "2") := "my_lab2")
    # $lab1
    # [1] "my_lab1"
    # $lab2
    # [1] "my_lab2"
    

    but in order to do this, it's just not possible to use =, they had to use := which is a function in R, not a special character, and they manually re-write the call when executing it.