166

I am looking for the reverse of get().

Given an object name, I wish to have the character string representing that object extracted directly from the object.

Trivial example with foo being the placeholder for the function I am looking for.

z <- data.frame(x=1:10, y=1:10)

test <- function(a){
  mean.x <- mean(a$x)
  print(foo(a))
  return(mean.x)}

test(z)

Would print:

  "z"

My work around, which is harder to implement in my current problem is:

test <- function(a="z"){
  mean.x <- mean(get(a)$x)
  print(a)
  return(mean.x)}

test("z")
MichaelChirico
  • 32,615
  • 13
  • 106
  • 186
Etienne Low-Décarie
  • 12,513
  • 15
  • 63
  • 87

4 Answers4

188

The old deparse-substitute trick:

a<-data.frame(x=1:10,y=1:10)
test<-function(z){
   mean.x<-mean(z$x)
   nm <-deparse(substitute(z))
   print(nm)
   return(mean.x)}
 
 test(a)
#[1] "a"   ... this is the side-effect of the print() call
#          ... you could have done something useful with that character value
#[1] 5.5   ... this is the result of the function call

Edit: Ran it with the new test-object

Note: this will not succeed inside a local function when a set of list items are passed from the first argument to lapply (and it also fails when an object is passed from a list given to a for-loop.) You would be able to extract the ".Names"-attribute and the order of processing from the structure result, if it were a named vector that were being processed.

> lapply( list(a=4,b=5), function(x) {nm <- deparse(substitute(x)); strsplit(nm, '\\[')} )
$a      # This "a" and the next one in the print output are put in after processing
$a[[1]]
[1] "X"    ""     "1L]]"  # Notice that there was no "a"


$b
$b[[1]]
[1] "X"    ""     "2L]]"

> lapply( c(a=4,b=5), function(x) {nm <- deparse(substitute(x)); strsplit(nm, '\\[')} )
$a
$a[[1]]   # but it's theoretically possible to extract when its an atomic vector
[1] "structure(c(4, 5), .Names = c(\"a\", \"b\"))" ""                                            
[3] "1L]]"                                        


$b
$b[[1]]
[1] "structure(c(4, 5), .Names = c(\"a\", \"b\"))" ""                                            
[3] "2L]]"  
IRTFM
  • 251,731
  • 20
  • 347
  • 472
18
deparse(quote(var))

My intuitive understanding In which the quote freeze the var or expression from evaluation and the deparse function which is the inverse of parse function makes that freezed symbol back to String

cloudscomputes
  • 1,009
  • 9
  • 18
7

Note that for print methods the behavior can be different.

print.foo=function(x){ print(deparse(substitute(x))) }
test = list(a=1, b=2)
class(test)="foo"
#this shows "test" as expected
print(test)

#this (just typing 'test' on the R command line)
test
#shows
#"structure(list(a = 1, b = 2), .Names = c(\"a\", \"b\"), class = \"foo\")"

Other comments I've seen on forums suggests that the last behavior is unavoidable. This is unfortunate if you are writing print methods for packages.

Eli Holmes
  • 576
  • 6
  • 10
  • Perhaps it should be: `print.foo=function(x){ cat(deparse(substitute(x))) }` or `print.foo=function(x){ print(deparse(substitute(x)), quote=FALSE) }` – IRTFM Nov 30 '13 at 18:58
  • 1
    Or `print.foo=function(x){ print.default(as.list(x)) }` – IRTFM Nov 30 '13 at 19:05
  • `as.list()` wouldn't work since 'test' could be anything. I just used a list in my toy example. – Eli Holmes Aug 15 '20 at 15:38
  • R 3.6 update. There is now a little bit of a change to the behavior but it is still not fixed. `print(test)` produces `test` while `test` on the command line produces `x` (not `test` as you want). All these have the same behavior. `print.foo=function(x){ print(deparse(substitute(x))) }` or `print.foo=function(x){ cat(deparse(substitute(x))) }` or `print.foo=function(x){ print(deparse(substitute(x)), quote=FALSE) }` – Eli Holmes Aug 15 '20 at 15:39
0

To elaborate on Eli Holmes' answer:

  1. myfunc works beautifully
  2. I was tempted to call it within another function (as discussed in his Aug 15, '20 comment)
  3. Fail
  4. Within a function, coded directly (rather than called from an external function), the deparse(substitute() trick works well.
  5. This is all implicit in his answer, but for the benefit of peeps with my degree of obliviousness, I wanted to spell it out.
an_object <- mtcars
myfunc <- function(x) deparse(substitute(x))

myfunc(an_object)
#> [1] "an_object"

# called within another function 
wrapper <- function(x){
  myfunc(x)
}

wrapper(an_object)
#> [1] "x"
Richard Careaga
  • 580
  • 1
  • 4
  • 10