如何创建R闭包的独立副本?保留当前状态且环境变更互不影响
复制R闭包并使其状态独立的实现方案
可以实现将R闭包复制为独立的新对象,保留原状态且不受原闭包后续变更影响。你当前遇到的Error in { : could not find function "{"错误,是因为复制时错误设置了新环境的父环境,导致闭包无法找到基础内置函数。
错误原因
你在创建新环境时使用了parent = emptyenv(),这个环境没有任何父环境。而R的函数查找是沿着环境链向上进行的,所以闭包执行时找不到{这类基础语法相关的内置函数,从而触发报错。
修正后的代码
# 基础递增闭包 inc <- function() { i <- 0 function(x = 1) { i <<- i + x i } } copyClosure <- function(x) { oldEnv <- environment(x) # 设置新环境的父环境为原闭包环境的父环境,而非空环境 newEnv <- new.env(parent = parent.env(oldEnv)) # 复制原闭包的函数体 ret <- x # 将复制后的函数绑定到新环境 environment(ret) <- newEnv # 复制原环境中的所有对象到新环境 objs <- ls(envir = oldEnv, all.names = TRUE, sorted = FALSE) for (ii in objs) { assign(x = ii, envir = newEnv, value = get(x = ii, envir = oldEnv)) } return(ret) } # 测试流程 # 原闭包对象 foo <- inc() foo(5) # 输出5 # 复制闭包 bar <- copyClosure(foo) # 验证初始状态一致 identical(get("i", envir = environment(foo)), get("i", envir = environment(bar))) # 返回TRUE # 修改原闭包状态,验证两者独立 foo(5) # 输出10 identical(get("i", envir = environment(foo)), get("i", envir = environment(bar))) # 返回FALSE,说明状态已分离 # 调用复制后的闭包,正常执行 bar(5) # 输出10
说明
- 修正后的
copyClosure函数将新环境的父环境设置为原闭包环境的父环境,这样新环境既能继承原闭包的变量,又能通过父环境链找到R的基础内置函数。 - 复制后的闭包
bar会保留原闭包foo的当前状态,且后续对foo的状态修改不会影响bar,反之亦然。
内容的提问来源于stack exchange,提问作者oepix
相关产品推荐
相关产品推荐

