Celdor Celdor - 12 days ago 6
R Question

Understanding evaluation of input arguments of functions

I am reading Advanced R by Hadley Wickham where some very good exercises are provided. One of them asks for description of this function:

f1 <- function(x = {y <- 1; 2}, y = 0) {
x + y
}
f1()


Can someone help me to understand why it returns 3? I know there is something called lazy evaluation of the input arguments, and e.g. another exercise asks for description of this function

f2 <- function(x = z) {
z <- 100
x
}
f2()


and I correctly predicted to be 100;
x
gets value of
z
which is evaluated inside a function, and then x is returned. I cannot figure out what happens in
f1()
, though.

Thanks.

Answer

See this from https://cran.r-project.org/doc/manuals/r-patched/R-lang.html#Evaluation:

When a function is called or invoked a new evaluation frame is created. In this frame the formal arguments are matched with the supplied arguments according to the rules given in Argument matching. The statements in the body of the function are evaluated sequentially in this environment frame. ... R has a form of lazy evaluation of function arguments. Arguments are not evaluated until needed.

and this from https://cran.r-project.org/doc/manuals/r-patched/R-lang.html#Arguments:

Default values for arguments can be specified using the special form ‘name = expression’. In this case, if the user does not specify a value for the argument when the function is invoked the expression will be associated with the corresponding symbol. When a value is needed the expression is evaluated in the evaluation frame of the function.

In summary, if the parameter does not have user-specified value, its default value will be evaluated in the function's evaluation frame. So y is not evalulated at first. When the default of x is evaluated in the function's evaluation frame, y will be modified to 1, then x will be set to 2. As y is already found, the default argument has no change to be evaluated. if you try f1(y = 1) and f1(y = 2), the results are still 3.