如何清除 '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
我一直在关注一个动态编程教程,并尝试为 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