0

我正在递归地构造一个近似函数(adaboost)。我想在此过程中创建生成的学习函数(不要将近似值直接应用于我的测试数据,而是保留导致它的函数)

不幸的是,R 似乎在使用变量名很久后更新了变量名所引用的值。

#defined in plyr as well
id <- function(x) {x}

#my first classifier 
modelprevious <- function(inputx, k) { k(0)}

#one step of my superb model
modelf <- function(x) 2*x #for instance

#I update my classifier
modelCurrent <- function(inputx, k) 
                 { modelprevious(inputx, function(res) {k(res + modelf(inputx))})}

#it works
modelCurrent(2,id) #4

#Problem
modelf <- function(x) 3*x
modelCurrent(2,id) #6 WTF !! 

具有相同参数的相同函数返回不同的东西,这很烦人!

那么如何捕获由 modelf 表示的,以便生成的函数仅取决于绑定时的参数,而不是某个全局状态?


考虑到这个问题,我不明白如果一个人不能接触局部变量,如何在 R 中构建递归函数,除了经历引用/解析的丑陋黑客

4

1 回答 1

10

你需要一个工厂:

modelCurrent = function(mf){
  return(function(inputx,k){
    modelprevious(
      inputx,
      function(res){
        k(res+mf(inputx))
      } # function(res)
      ) # modelprevious
  } # inner function
         ) # return
} # top function

现在您使用工厂创建具有modelf您希望它使用的功能的模型:

> modelf <- function(x) 2*x
> m1 = modelCurrent(modelf)
> m1(2,id)
[1] 4
> modelf <- function(x) 3*x
> m1(2,id) # no change.
[1] 4

您始终可以临时制作它们:

> modelCurrent(modelf)(2,id)
[1] 6

在那里你可以看到工厂使用 的当前定义创建了一个函数modelf,所以它乘以 3。

最后一个巨大的WTF!?!那会打击你的。仔细观察:

> modelf <- function(x) 2*x
> m1 = modelCurrent(modelf)
> m1(2,id)
[1] 4
>
> m1 = modelCurrent(modelf) # create a function using the 2* modelf
> modelf <- function(x) 3*x # change modelf...
> m1(2,id) # WTF?!
[1] 6

这是因为当调用工厂时,mf不评估 - 那是因为不调用内部函数,并且mf在调用内部函数之前不使用。

诀窍是强制评估mf外部函数中的 ,通常使用force

modelCurrent = function(mf){
  force(mf)
  return(function(inputx,k){
    modelprevious(
      inputx,
      function(res){
        k(res+mf(inputx))
      } # function(res)
      ) # modelprevious
  } # inner function
         ) # return
} # top function

这导致我过早秃顶,因为如果您忘记了这一点并认为发生了一些奇怪的错误,然后尝试print(mf)固定在原地查看发生了什么,您将进行评估mf,从而获得您想要的行为。通过检查数据,你改变了它!一只海森堡!

于 2013-08-11T07:35:49.187 回答