Maxim Andreev
Maxim Andreev

Reputation: 197

Call Arguments of Function inside Function / R language

I have a function:

func <- function (x)
{
  arguments <- match.call()
  return(arguments)
}

1) If I call my function with specifying argument in the call:

func("value")

I get:

func(x = "value") 

2) If I call my function by passing a variable:

my_variable <-"value"
func(my_variable)

I get:

func(x = my_variable)

Why is the first and the second result different?
Can I somehow get in the second call "func(x = "value")"?

I'm thinking my problem is that the Environment inside a function simply doesn't contain values if they were passed by variables. The Environment contains only names of variables for further lookup. Is there a way to follow such reference and get value from inside a function?

Upvotes: 0

Views: 2386

Answers (2)

Tomas Kalibera
Tomas Kalibera

Reputation: 1061

In R, when you pass my_variable as formal argument x into a function, the value of my_variable will only be retrieved when the function tries to read x (if it does not use x, my_variable will not be read at all). The same applies when you pass more complicated arguments, such as func(x = compute_my_variable()) -- the call to compute_my_variable will take place when func tries to read x (this is referred to as lazy evaluation).

Given lazy evaluation, what you are trying to do is not well defined because of side effects - in which order would you like to evaluate the arguments? Which arguments would you like to evaluate at all? (note a function can just take an expression for its argument using substitute, but not evaluate it). As a side effect, compute_my_variable could modify something that would impact the result of another argument of func. This can happen even when you only passed variables and constants as arguments (function func could modify some of the variables that will be later read, or even reading a variable such as my_variable could trigger code that would modify some of the variables that will be read later, e.g. with active bindings or delayed assignment).

So, if all you want to do is to log how a function was called, you can use sys.call (or match.call but that indeed expands argument names, etc). If you wanted a more complete stacktrace, you can use e.g. traceback(1).

If for some reason you really wanted values of all arguments, say as if they were all read in the order of match.call, which is the order in which they are declared, you can do it using eval (returns them as list):

lapply(as.list(match.call())[-1], eval)

Upvotes: 2

carlo
carlo

Reputation: 260

can't you simply

return paste('func(x =', x, ')')

Upvotes: 0

Related Questions