继续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
}
但是如果一个或多个args没有默认参数,它将不起作用:
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 :(得分: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())
}
答案 1 :(得分:0)
对你来说有点晚了,但可能会帮助其他人解决同样的问题。 “函数”错误的“无效形式参数列表”是RStudio中的错误。当由于某种原因在函数的结束括号(})中设置断点时会发生这种情况。
当我在运行它时编辑R脚本时发生了这种情况,然后R工作室崩溃了。断点保留在原始线上,但线条已移动......
你需要做的就是删除断点,你很好。
答案 2 :(得分: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
但是,您必须在形式列表中提供以获得强制性参数的价值。