0

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

mharinga
  • 1,708
  • 10
  • 23
  • 1
    Why do you want this? What is you main issue? – Onyambu Aug 24 '22 at 18:02
  • 1
    This is not possible. You need to elaborate further as to what exactly you need. eg `x <- "mpg"` when should `sfn(x)` return `x` and when should it return the stored value in x ie `mpg`?? You need to clearly state your problem. eg in the examples given, the function returns the argument passed and not what the argument stores. ig it does not return the mpg stores – Onyambu Aug 24 '22 at 18:07
  • 1
    What exactly is the problem you are trying to solve? This here seems like an intermediary question. consider looking at the [`xyproblem`](https://xyproblem.info/) – Onyambu Aug 24 '22 at 18:09
  • @onyambu Thank you for response, my apologies for not being clear. I updated my question. – mharinga Aug 24 '22 at 18:24
  • 2
    This question shows why it is almost never a good idea to use NSE. If you must use it then use two arguments, one with NSE and one without. Look at the design of `rm` where it uses dot dot dot for the NSE arguments and list= for the SE version. – G. Grothendieck Aug 24 '22 at 18:31

1 Answers1

1

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.

MrFlick
  • 195,160
  • 17
  • 277
  • 295
  • 1
    OP has not properly defined his problem. eg `x<-"mpg"` what should be the output of `sfn(x)`? – Onyambu Aug 24 '22 at 18:27