R - using substitution inside a nested function

I have a function that can be nested ( Inner

) and some other function (this function will not be known at all) that I call Outer

, and I would like to Inner

be able to produce the same result regardless of the wrapper function ( Outer

in the following case) ...

Inner <- function(x,baz,bang){
  # code stuff things ...
  x.prime = as.character(substitute(x))
  return(c(x.prime,y,z))
}

Outer <- function(y){
  Inner(y)
}
Inner(a)
# "a" "stuff" "things" , which is what I'm expecting, in particular the "a".
Outer(a)
# "y" .... , but I was expecting to get "a"?

      

Of course, I'm not sure if I'm using a replacement if someone knows a better method.

Does anyone have any hints on how to get Inner to output the same result, whether it is nested or not?

early.

+3


source to share


1 answer


Here's a general outline to help you solve your problem:

Inner <- function(x) {
  my.call <- quote(substitute(x))    # we quote this here because we are going to re-use this expression
  var.name <- eval(my.call)

  for(i in rev(head(sys.frames(), -1L))) { # First frame doesn't matter since we already substituted for first level, reverse since sys.frames is in order of evaluation, and we want to go in reverse order
    my.call[[2]] <- var.name         # this is where we re-use it, modified to replace the variable
    var.name <- eval(my.call, i)
  }
  return(var.name)
}
Outer <- function(y) Inner(y)
Outer2 <- function(z) Outer(z)

      

Now run the functions:

Inner(1 + 1)
# 1 + 1
Outer(2 + 2)
# 2 + 2
Outer2(3 + 3)
# 3 + 3

      

Inner always returns the outermost expression (you don't see y

or z

ever, just an expression typed into .GlobalEnv

.



The trick here is to use sys.frames()

and reuse substitute

until we get to the top level.

Note that all "Outer" functions are assumed to simply forward their argument to the next inner one. Things will probably be much more difficult / impossible if you have something like:

Outer <- function(y) Inner(y + 1)

      

This code doesn't test for this type of problem, but you probably should in your code. Also, keep in mind that this assumes that your functions will only be called from the R command line. If someone wraps their functions around you, you might get unexpected results.

+7


source







All Articles