8

The title isn't super descriptive as the problem is longer than a reasonable title I could think of could display.

I want to have a function that grabs object names from other functions that can be used as arguments in another function. Here's a barebones attempt:

grab <- function(x) {
    as.character(substitute(x))
}

FUN <- function(foo, bar = grab(foo)) {
    bar
}

FUN(mtcars)

Here I's want FUN to return the character string "mtcars" but it returns "foo". How could a make a grab function that does this (I want to do this because I'm going to use this as the default to a txt/csv etc file. It's a convenience setting.

Here are some unsuccessful attempts (but I want to have a generic grab function):

FUN2 <- function(foo, bar = as.character(substitute(bar))) {
   bar
}

FUN2(mtcars)

#==================

FUN3 <- function(foo, bar) {
    if(missing(bar)) bar <- foo
    as.character(substitute(bar))
}

FUN3(mtcars)

Real life-ish example:

real_example <- function(obj, file = grab(obj)) {
    write.csv(obj, file = sprintf("%s.csv", file))
}
Tyler Rinker
  • 108,132
  • 65
  • 322
  • 519
  • Feel free to edit or edit title to make this more clear. – Tyler Rinker Sep 21 '13 at 20:21
  • This question looks very similar: http://stackoverflow.com/questions/5754367/using-substitute-to-get-argument-name-with – Frank Sep 21 '13 at 20:45
  • @Frank did you get any of those responses to work? – Tyler Rinker Sep 21 '13 at 20:48
  • 1
    @TylerRinker I haven't tried everything, but this roughly does the same thing: `(function(x,y=get_args()))('mtcars')` where `get_args` is from http://stackoverflow.com/questions/17256834/getting-the-arguments-of-a-parent-function-in-r-with-names – Frank Sep 21 '13 at 20:57

2 Answers2

6

You could try sys.call to get access to the parent call:

## "which" is the number of the argument of interest
grab <- function(which) {
  ## which + 1, because [1] == name of function/call
  ## and arguments are 2:n
  as.character(sys.call(-1L)[which+1L])
}

FUN <- function(foo, bar = grab(1L)) {
  bar
}

FUN(mtcars)
# "mtcars"
sgibb
  • 25,396
  • 3
  • 68
  • 74
  • This is the behavior I am looking for. I'll hold off checking as the answer in case others have a better option (i.e., someone points out something faulty with this). – Tyler Rinker Sep 21 '13 at 20:38
  • +1. Yeah, as Tyler says, if there's nothing wrong with doing it this way (instead of passing the name "mtcars" and using `get`), I might use this, too. – Frank Sep 21 '13 at 20:40
6

How about this?

grab <- function(x) as.character(x[["foo"]])
FUN <- function(foo, bar=grab(match.call())) { bar }

FUN(mtcars)
# [1] "mtcars"
Arun
  • 116,683
  • 26
  • 284
  • 387