Paul Hiemstra
Paul Hiemstra

Reputation: 60924

Finding the name of the object a function returns to

My question is the following. Given the following function:

spam <- function() {
  cat("eggs\n")
}

bla <- spam()

I want to find the name of the object the function is returning its content to. In the example bla <- spam() this would be bla. Using match.call I can find the call that was performed:

match.call()
function() {
      cat("eggs\n")
    }   

this, however, does not include the name of the object the function returns to. I've looked around on the R-help list, google and SO, but could not find anything useful. Any suggestions how to proceed?

Background From the replies I gather that what I want is a bit on the esotheric side. I'd explain where I'm coming from, this might shed some light on my motives. The context I'm working in has to do with testing, and more specifically, testing whether or not a certain object changes in time (e.g. model output).

Normally a user will write a bunch of code that generates an object, save it and compare the saved object to newly generated objects as time goes on. The user can do this using the following function:

spam <- testReferenceChange(expression)

Normally this function will read the reference and generate a new object, which the user can compare to each other. For regenerating the reference file, I wanted to use the exact same code. I do this by changing a global option (see options and getOption), recalculate. We running this function in the recalculation mode, new references are stored. And now for the reason to my question. In saving the reference to file (using save()) I wanted to use the name of the object the user returns to, combined with a date, to create a unique name.

Upvotes: 4

Views: 180

Answers (2)

Dominic Comtois
Dominic Comtois

Reputation: 10401

I had a similar need and thought of that solution... It's probably not perfect but so far I had good results with it.

getLastCreatedObj <- function() {
  tmpfile <- tempfile("hist", fileext = ".txt")
  savehistory(file = tmpfile)
  last_command <- tail(readLines(tmpfile), 2)[1]
  unlink(tmpfile)
  if (grepl("^[a-zA-Z_.0-9]+\\s*(<-|=)", last_command)) {
    all_names <- all.names(as.expression(parse(text = s)))
    varname <- all_names[grep("(<-|=)", all_names) + 1]
    return(varname)
  }
  return(NULL)
}

Note that you can't use it in a package; it fails check with the message 'savehistory' can only be used in Rgui and Rterm.

Upvotes: 0

Tommy
Tommy

Reputation: 40803

...I find it hard to imagine why you would want this. Also, your spam function returns NULL so it seems even more pointless...

Nevertheless, the simplest/cleanest way to do this is to pass in the name to the spam function!

spam <- function(name) {
   cat(name, "<- eggs\n")
   42 # return a value
}


bla <- spam("bla")

Advancing to the next level, you could have spam do the assignment. You can also play with substitute to allow specifying the name without quotes:

spam <- function(name) {
   name <- as.character(substitute(name))
   cat(name, "<- eggs\n")
   value <- 42
   assign(name, value, parent.frame())
}

spam(bla)
bla # 42

Upvotes: 3

Related Questions