Search code examples
rnse

Using external vector with NSE


Let's say I have the following function:

sfn <- function(x){
  gsub('"', "", deparse(substitute(x)))
}

Then sfn() returns "mpg" (for both mpg and "mpg"), this is the result I would like to get.


sfn("mpg")
#> [1] "mpg"
sfn(mpg)
#> [1] "mpg"

However, with an external vector it gets ambiguous. Is there a way to get "mpg" returned (with the same function sfn()) instead of "x[1]"? Only an external vector should be used in case the user specifies this (e.g. with a helper function). Like the following example with extvecfn() to indicate that x is an external vector:


x <- c("mpg", "cyl")

# Desired output
sfn(extvecfn(x[1]))
#> [1] "mpg"

# Desired output
sfn(x)
#> [1] "x"

Created on 2022-08-24 with reprex v2.0.2


Solution

  • I would very much not recommend such a function, but technically you could look to see if someone has passed an expression, and if they did, then you can evaluate it. So you could do

    sfn <- function(x){
      expr <- substitute(x)
      if(is.call(expr) && expr[[1]]==quote(extvecfn)) {
        as.character(eval.parent(expr[[2]]))
      } else if (is.character(expr)) {
        x
      } else {
        deparse(expr)
      }
    }
    sfn("mpg")
    # [1] "mpg"
    sfn(mpg)
    # [1] "mpg"
    x <- c("mpg", "cyl")
    sfn(extvecfn(x[1]))
    # [1] "mpg"
    sfn(x[1])
    # [1] "x[1]"
    sfn(x)
    # [1] "x"
    

    But this just makes it very difficult to work with such a function in a more general way. In most cases this is just a bad idea. It's better to have separate parameters for variable values and character labels. In most cases you can have a default value for the label using deparse but it's much better if the user has some other way to set the value.