0

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?

1
  • The call is not evaluated, so how should my_variable be substituted by "value"? What are you trying to achieve? Commented Oct 28, 2016 at 13:27

2 Answers 2

2

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)
Sign up to request clarification or add additional context in comments.

Comments

0

can't you simply

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

3 Comments

I can but I didn't want to code all possible variables by hand. My functions is used in the call to web-API with 15+ possible parametrs.
but you just want a string, don't you? can't you still use the paste function like this:
sorry, I didn't finish the comment: l= as.list(match.call())[-1]; return(paste('func(, paste(names(l), l, sep=' = ', collapse=', '), ')'))

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.