如何清除 'memo' 或更好地理解 R 中使用超赋值“<<-”的记忆递归函数的作用域

How to clear the 'memo' or better understand scoping in R with memoised recursive functions using superassignment "<<-"

我一直在关注一个动态编程教程,并尝试为 R 调整他们的代码。我在很多关于 R 中的记忆的帖子中看到的解决方案首先创建一个本地环境,在该环境中创建备忘录对象。该备忘录对象在函数调用之间没有得到 'cleared'。对于一些常见的用途,我可以看到这实际上是一个好处——如果您要求函数进行的计算基本上是 'fixed',那么为什么要在一个会话中多次执行这些计算?但是对于这个例子来说,这是一个问题。

这个递归函数接受一个目标整数和一个整数列表,returns 'TRUE' 如果列表的任何组合(有替换)可以求和到目标,否则 'FALSE'.

cS <- function(targetSum, numbers){

  if(targetSum < 0){ return(FALSE) }
  if(targetSum == 0){ return(TRUE) }
  remainder <- list()

  for(i in 1:length(numbers)){
    remainder[i] = targetSum - numbers[i]
    if(cS(remainder[[i]], numbers) == TRUE){ return(TRUE) }
  }

  return(FALSE)

}

cS(7, c(2,3)) # TRUE
cS(7, c(5,3,4,7)) # TRUE
cS(7, c(2,4)) # FALSE

我试图记住它:

cSm <- local({

  key <- list()

  function(targetSum, numbers){

    valueName <- as.character(targetSum)
    if(!is.null(key[[valueName]])){ return(key[[valueName]]) }
    if(targetSum < 0){ return(FALSE) }
    if(targetSum == 0){ return(TRUE) }

    remainder <- list()
    for(i in 1:length(numbers)){
      remainder[i] = targetSum - numbers[i]
      # browser()
      if(Recall(remainder[[i]], numbers) == TRUE){ 
        valueName <- as.character(remainder[[i]])
        key[[valueName]] <<- TRUE
        return(TRUE)
      } 
    }

    key[[valueName]] <<- FALSE
    # print(key)
    return(FALSE)

  }
})

cSm(7, c(2,3)) # TRUE
cSm(7, c(5,3,4,7)) # TRUE
cSm(7, c(2,4)) # expected FALSE, returns TRUE

>get("key", environment(cSm)) # there are 'leftovers' from prior calls

$`1`
[1] FALSE

$`0`
[1] TRUE

$`3`
[1] TRUE

$`5`
[1] TRUE

$`2`
[1] FALSE

$`4`
[1] TRUE

为什么 local() 中第一行的 key <- list() 没有在每次调用该函数时擦除空白?如果我在每次调用 cSm 之间的函数环境中创建 key <- NULL,它会按预期工作,但我想做得更好。

>assign("key", NULL, envir = environment(cSm))
>get("key", envir = environment(cSm))

NULL

>cSm(7, c(2,4)) # FALSE

[1] FALSE

>get("key", envir = environment(cSm))

$`1`
[1] FALSE

$`3`
[1] FALSE

$`5`
[1] FALSE

$`7`
[1] FALSE

有没有我没有看到的简单解决方案?我应该尽量避免使用 <<- 吗?我有哪些选择?

尝试运行 csm 中的递归:

cSm <- function(targetSum, numbers){
  
  key <- list()
  
  recurser <- function(targetSum,numbers) {
    
    valueName <- as.character(targetSum)
    if(!is.null(key[[valueName]])){ return(key[[valueName]]) }
    if(targetSum < 0){ return(FALSE) }
    if(targetSum == 0){ return(TRUE) }
    
    remainder <- list()
    for(i in 1:length(numbers)){
      remainder[i] = targetSum - numbers[i]
      # browser()
      if(Recall(remainder[[i]], numbers) == TRUE){ 
        valueName <- as.character(remainder[[i]])
        key[[valueName]] <<- TRUE
        return(TRUE)
      } 
    }
    
    key[[valueName]] <<- FALSE
    # print(key)
    return(FALSE)
    
  }
  
  
  recurser(targetSum, numbers)
}



cSm(7, c(2,3)) # TRUE
cSm(7, c(5,3,4,7)) # TRUE
cSm(7, c(2,4)) # FALSE