2015-06-05 3 views
3

Исходя из How to create an R function programmatically?Создать функцию R программно с помощью дополнительных нестандартных аргументов

Я хочу построить функции R из их компонентов, как это:

testfn <- function(..., expression){ 
    args <- substitute(alist(...)) 
    body <- substitute(expression) 
    eval(call("function", as.pairlist(eval(args)), body), parent.frame()) 
} 

Это прекрасно работает, если есть значения по умолчанию:

testfn(x = 4, y = 5, expression = { 
    y <- y + 2 
    x + y 
}) 

=> 
function (x = 4, y = 5) 
{ 
    y <- y + 2 
    x + y 
} 

Но это не будет работать, если нет по умолчанию аргумента для одного или нескольких аргументов:

testfn(x = 4, y, expression = { 
    y <- y + 2 
    x + y 
}) 

=> 
Error in eval(expr, envir, enclos) : 
invalid formal argument list for "function" 

Я могу поставить = в списке агда, чтобы получить эту работу:

testfn(x = 4, y = , expression = { 
    y <- y + 2 
    x + y 
}) 

=> 
function (x = 4, y) 
{ 
    y <- y + 2 
    x + y 
} 

Но я не хочу, чтобы обеспечить соблюдение этого в аргументах функции. Я попытался отредактировать ассоциативный список в функции, но когда я делаю это, я получаю другую неверную формальную ошибку списка аргументов:

testfn2 <- function(..., expression){ 
    args <- substitute(alist(...)) 
    body <- substitute(expression) 
    for (arg in 2:length(args)){ 
    if(names(myargs)[arg] == ""){ 
     args[[arg]] <- as.name(paste(as.character(args)[arg], "=")) 
    } 
    } 
    eval(call("function", as.pairlist(eval(args)), body), parent.frame()) 
} 

testfn2(x = 4, y, expression = { 
    y <- y + 2 
    x + y 
}) 

=> 
Error in eval(expr, envir, enclos) : 
invalid formal argument list for "function" 

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

+0

Вы пытались с 'missing (y)'? чтобы проверить, присутствует ли 'y' в вызове. –

+0

Проблема заключается в том, чтобы сделать вызов, при построении форматов для новой функции. – dspringate

ответ

1

Вот один не очень элегантный способ сделать это:

testfn <- function(..., expression){ 
    args <- eval(substitute(alist(...))) 
    body <- substitute(expression) 

    ## Fix for missing default values 
    tmp <- names(args) 
    if (is.null(tmp)) tmp <- rep("", length(args)) 
    names(args)[tmp==""] <- args[tmp==""] 
    args[tmp==""] <- list(NULL) 

    eval(call("function", as.pairlist(args), body), parent.frame()) 
} 
+0

Спасибо @juba. Это почти так, но это означает, что по умолчанию для y задано значение «NULL», что немного отличается, потому что вы можете вызвать возвращенную функцию только с аргументом x, не вызывая ошибки. – dspringate

+0

@dspringate Извините, я не уверен, что понимаю, что вы имеете в виду. Если для 'y' не задано значение по умолчанию, вы хотите, чтобы сгенерированная функция выдавала ошибку? – juba

+0

Нет, я хочу сказать, что я хочу, чтобы возвращаемая функция была (в этом примере) функцией (x = 4, y) { y <- y + 2 x + y }, а не функция (x = 4, y = NULL) { y <- y + 2 x + y }, так что если эта функция будет вызвана, она вернет отсутствующую без ошибки по умолчанию, если y не предоставляется – dspringate

0

немного поздно для вас, но может помочь другим с той же проблемой. «Недопустимый формальный список аргументов для ошибки« function »- ошибка в RStudio. Это происходит, когда по какой-либо причине точка останова задается в концевой скобке (}) функции.

Это случилось со мной, когда я редактировал скрипт R во время его запуска, а затем студия R разбилась. точки останова были сохранены на исходных строках, но линии были перемещены ...

Все, что вам нужно сделать, это удалить точку останова, и вы в порядке.

0

Если я понимаю, что вы хотите сделать, передавая символ нулевой длины в качестве значения по умолчанию для у будет делать трюк:

не
> body <- expression(x + y) 
> 
> args <- list() 
> args[["y"]] <- alist(y=)$y #zero-length symbol 
> args[["x"]] <- 4 

> eval(call("function", as.pairlist(args), body[[1]])) 
function (y, x = 4) 
x + y 

Там нет другого пути, я нашел (кроме выше трюк с креном), чтобы создать один из них:

> as.symbol("") 
Error in as.symbol("") : attempt to use zero-length variable name 

Но это значение, которое вы должны предоставить в список формалей получить обязательный аргумент.

Смежные вопросы