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?
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.
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.
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.
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With