将参数传递给闭包(?)

时间:2012-06-08 20:06:17

标签: r closures

我正在尝试创建一个封闭的函数:

  • 处理一些数据,
  • cat()该数据的结果,
  • 根据readline()
  • 的结果请求用户输入(即通过cat()
  • 然后返回一个函数,其中返回函数的一个参数默认值是readline()输入的值。

此外,我希望返回函数的参数的剩余默认值是用户可解释的。也就是说,我不希望默认值是隐藏在父环境中的变量的变量名(这个规定排除了简单的参数传递)。具体来说,我希望arg()返回实际评估的数字等。

我已经在下面制作了这个解决方案,但感觉很笨拙和笨拙。是否有更优雅的方式来接近这个?

top <- function(year=1990, n.times=NULL){

if(is.null(n.times)){
    ###in the real function, data would be processed here
    ###results would be returned via cat and
    ###the user is prompted return values that reflect a decision
    ###made from the processed data
    n.times <- as.numeric(readline("how many times?"))
}


out <- function(year, n.times){
    ###in the real function, this is where most of the work would happen
    rep(year, n.times)
}

###this entire section below is clunky.
if( !identical( names(formals()), names(formals(out)) ) ){
     stop("internal error: mismatching formals")

}

pass.formals <- setdiff( names(formals()), "n.times")

formals(out)[pass.formals] <- formals()[pass.formals]
formals(out)$n.times <- n.times
out

}

x <- top()
x

1 个答案:

答案 0 :(得分:2)

对我来说一般来说都很好;我只做了一些不同的事情。

是否有任何理由认为top()out()的参数在某些情况下相符 办法?即,你需要identical检查吗?不确定,所以我把它拿出来了。这似乎与你有关 想要,并且稍微缩短:

top <- function(year=1990, n.times=NULL){
    if (is.null(n.times)) {
        n.times <- as.numeric(readline("how many times?"))
    }

    out <- function(year, n.times) {
        rep(year, n.times)
    }

    out.formals = formals(out)
    out.formals['n.times'] = n.times
    formals(out) = out.formals

    out
}

编辑如果你想使用超级R魔法,你可以写

top <- function(year=1990, n.times=NULL){
    if (is.null(n.times)) {
        n.times <- as.numeric(readline("how many times?"))
    }

    `formals<-`(
        function() {
            rep(year, n.times)
        },
        value=list(year=alist(x=)$x, n.times=n.times)
    )
}

编辑:你也可以使用DWin建议的东西(虽然我不能 让它与substitute)一起使用:

    out = function(year, n.times) {
        rep(year, n.times)
    }
    `formals<-`(out, v=`[[<-`(formals(out), 'n.times', n.times))

或使用bquote

    eval(bquote(
        function(year, n.times=.(n.times)) {
            rep(year, n.times)
        }
    )[-4L])

你有很多选择。