Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can a function parameter be used without mentioning it in the function body?

Tags:

r

I've been trying to learn more about R (and writing C extensions) and I thought it might help to read the source for some well known packages. I decided to start with rpart which is defined as:

rpart <- function(formula, data, weights, subset,
       na.action=na.rpart, method, model=FALSE, x=FALSE, y=TRUE,
       parms, control, cost, ...)

I did a quick search through the source and I don't see formula mentioned anywhere in the function body yet I know that somehow rpart is using that parameter. How is it that rpart is using formula without its name being in the function body?

like image 309
David Locke Avatar asked Apr 21 '09 23:04

David Locke


People also ask

Can we use a function as a parameter of another function?

You can use function handles as input arguments to other functions, which are called function functions. These functions evaluate mathematical expressions over a range of values.

What is the use of function as a parameter?

A parameter is a named variable passed into a function. Parameter variables are used to import arguments into functions. Note the difference between parameters and arguments: Function parameters are the names listed in the function's definition.

How do you pass a function as a parameter?

Function Call When calling a function with a function parameter, the value passed must be a pointer to a function. Use the function's name (without parentheses) for this: func(print); would call func , passing the print function to it.

Where are parameters passed to functions?

Parameter values to functions are stored on the stack as well, pushed immediately before the return address. Everything what lives on the stack (local variables, parameters etc.) can live in registers as well.


1 Answers

It's pretty tricky:

m <- match.call(expand.dots = FALSE)
# ...
m[[1L]] <- as.name("model.frame")
m <- eval(m, parent.frame())

The function uses match.call to find out how it is being called, modifies the call to replace the called function by model.frame, and calls it via eval with the parameters it received (although the part I replaced by # ... removes several of the parameters), and model.frame uses the formula parameter. See the documentation of match.call, eval, and model.frame, and experiment a little, e.g. try to understand what is happening here:

f <- function(formula, data) { 
  m <- match.call()
  m[[1L]] <- as.name('model.frame')
  eval(m, parent.frame())
}
f(x ~ y)
Error in eval(expr, envir, enclos) : object 'x' not found
x <- c(1,2,3)
f(x ~ y)
Error in eval(expr, envir, enclos) : object 'y' not found
y <- c(3,4,5)
f(x ~ y)
  x y
1 1 3
2 2 4
3 3 5
d <- as.data.frame(matrix(c(1,2,3,4),nrow=2))
names(d) <- c('foo', 'bar')
f(foo ~ bar, d)
  foo bar
1   1   3
2   2   4
like image 107
Jouni K. Seppänen Avatar answered Nov 14 '22 21:11

Jouni K. Seppänen