2009-04-21 4 views
7

Я пытался узнать больше о R (и писать расширения C), и я подумал, что это может помочь прочитать источник для некоторых известных пакетов. Я решил начать с rpart, который определяется как:Как использовать параметр функции без упоминания его в теле функции?

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

Я сделал быстрый поиск через источник, и я не вижу, формула упоминается нигде в теле функции все же я знаю, что каким-то образом rpart использует этот параметр. Как получается, что rpart использует формулу, если ее имя не находится в теле функции?

ответ

9

Это довольно сложно:

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

Функция использует match.call, чтобы узнать, как она вызывается, изменяет вызов для замены вызываемой функции по model.frame, и называет его помощью eval с параметрами он получил (хотя часть I, замененная на # ..., удаляет несколько параметров), а model.frame использует параметр formula. См. Документацию по match.call, eval и model.frame, и немного экспериментируйте, например. попытайтесь понять, что здесь происходит:

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