2015-06-05 199 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 

但它是您必须在形式列表中提供的值才能获得强制性参数。