2015-06-05 237 views
3

創建一個R函數編程方式從How to create an R function programmatically?與可選的非默認參數

我想從它們的組件這樣建立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" 

我可以把=在ARG列表中得到這個工作:

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

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

但我不希望在函數的參數來執行此操作。我曾嘗試編輯ALIST的功能,但是當我這樣做,我得到另一個無效正式的參數列表錯誤:

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從字符串中構建一個新的alist,但這意味着我不能有作爲參數。

+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

如果我理解你想做的事,傳遞一個零長度符號作爲默認的Y值就可以了什麼:

> 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 

還有,我發現沒有其他的方法(除了上述伎倆與alist)生成其中之一:

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

但它是您必須在形式列表中提供的值才能獲得強制性參數。