R中的懒惰评估是否受到影响?

Mat*_*ert 21 r lazy-evaluation assign

我读了这个关于重命名对象的基本问题和@Shane对它的回答,指着我懒惰的评价.现在我想知道是否assign也懒得评价.就像这里一样:

assign("someNewName",someOldObject)
rm(someOldObject)
Run Code Online (Sandbox Code Playgroud)

为什么我想知道这样做的原因是以下用例:假设我有10K + R对象各自有两个属性叫originalNameadditionalName.现在我想编写一个函数,可以有效地让用户从一个名称切换到另一个名称,而不会丢失这两个属性.粗略喜欢这个......

编辑:基于@Hadley的输入我改变了我的代码.

switchObjectName <- function(x) {
  n1 <- attributes(x)$originalName
  n2 <- attributes(x)$additionalName
  objName <- deparse(substitute(x))
  if(objName == n1) {
    delayedAssign(n2,x,assign.env=.GlobalEnv)
  } else {
    delayedAssign(n1,x,assign.env=.GlobalEnv)
  }
  rm(list=c(objName),envir=.GlobalEnv)    
}
Run Code Online (Sandbox Code Playgroud)

这种方法效果很好,但是我说这rm句话是正确的.rm(objName,envir=.GlobalEnv)虽然objName肯定是一个字符因为它是结果,但我试过但是无法使它工作deparse(substitute(x).

Tom*_*era 5

R语言通常具有值语义.的分配x <- y意味着,xy将是相同的对象的独立副本(上更新yx将是独立的).一个简单的实现x <- y将始终为其分配内存x并完全复制y到其中.GNU-R使用写入时复制机制,它会推迟复制,直到更新实际发生,这样可以节省内存/执行时间,以防万一.R用户不必了解此优化,它完全透明(除了一些罕见的情况,如内存不足错误).这种机制适用于写作x <- yassign("x", y)同等的作业.

延迟评估是语言设计的一部分,R用户/程序员可以看到.作为参数传递给函数foo(ls())的表达式,例如在传递的表达式中ls(),只有在被调用函数的实现需要时才会被懒惰地评估.

delayedAssign是一个低级函数,R用户/程序员可以看到,但它实际上只用于延迟加载包,在用户程序中不需要.delayedAssign允许指定一个表达式来计算变量的值; 只有当/第一次读取变量时,计算才会延迟发生.

因此,为了回答这个问题,R中的赋值总是"懒惰",因为使用了写时复制机制.赋值右侧的计算也可以是惰性的(使用delayedAssign),但用户程序不应该需要/使用它.

我认为对于变量的"重命名",不需要使用delayedAssign(因为没有计算右侧).它只会使情况变得更加复杂,并且可能会因为簿记而导致性能开销delayedAssign.如果我不得不重命名变量,我会使用普通的赋值.

为了清楚代码,我还会尽可能地避免从环境中删除变量,甚至从函数中分配到全局环境中,例如,我只需创建一个新列表并将新绑定(变量)插入其中.

已经提到了写入时复制机制,使用GNU-R中的当前实现,任何所描述的解决方案都可能导致在没有重命名变量的情况下不需要的存储器复制.在R级别无法避免这种情况.