R中的惰性评估–分配会受到影响吗? [英] Lazy evaluation in R – is assign affected?
问题描述
我阅读了有关重命名对象和@Shane的基本问题的答案,这使我感到懒惰的评价.现在我想知道assign
是否也被懒惰地求值.就像这里:
I read this basic question on renaming objects and @Shane 's answer to it, pointing me to lazy evaluation. Now I wonder if assign
is evaluated lazily, too. Just like here:
assign("someNewName",someOldObject)
rm(someOldObject)
我对此感到疑惑的原因是以下用例:假设我有10K + R个对象,每个对象都有两个名为originalName
和additionalName
的属性.现在,我想编写一个函数,该函数可以有效地使用户从一个名称切换到另一个名称,而又不会丢失这两个属性.大概是这样...
The reason why I wonder about this is the following use case: Assume I got 10K+ R objects each of which has two attributes called originalName
and additionalName
. Now I want to write a function that can efficiently let the user switch from one name to the other without losing these two attributes. Roughly like this...
基于@Hadley的输入,我更改了代码.
based on @Hadley's input I have changed my code.
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)
}
这很好用,但是在正确使用rm
语句时遇到了很多麻烦.我尝试了rm(objName,envir=.GlobalEnv)
,但是虽然objName绝对是一个字符,但它却无法正常工作,原因是它是deparse(substitute(x)
的结果.
this works well, but I had quite some trouble to get the rm
statement right. I tried rm(objName,envir=.GlobalEnv)
but could not get it to work though objName is definitely a character cause it is the result of deparse(substitute(x)
.
推荐答案
R语言通常具有值语义.赋值x <- y
表示x
和y
将是同一对象的独立副本(y
和x
的更新将是独立的).天真的x <- y
实现将始终为x
分配内存,并将y
完全复制到其中. GNU-R而是使用写时复制机制,它将复制推迟到实际发生更新时进行,这样可以在不发生更新的情况下节省内存/执行时间. R用户不必了解此优化,它是完全透明的(除了一些罕见的情况,如内存不足错误).此机制适用于均写为x <- y
和assign("x", y)
的赋值.
The R language generally has value semantics. The assignment x <- y
means that x
and y
will be independent copies of the same object (updates on y
and x
will be independent). A naive implementation of x <- y
would always allocate memory for x
and fully copy y
into it. GNU-R instead uses a copy-on-write mechanism, it would postpone the copy until an update actually happens, which saves memory/execution time in case it does not happen. R users do not have to know about this optimization, it is fully transparent (except some rare cases like out-of-memory errors). This mechanism applies to assignment written as x <- y
and assign("x", y)
equally.
惰性评估是该语言设计的一部分,R用户/程序员可以看到.作为参数传递给函数的表达式,例如在foo(ls())
中,传递的表达式为ls()
,只有在被调用函数的实现需要且仅在需要时才懒惰地对其求值.
Lazy evaluation is part of the design of the language and is visible to R users/programmers. Expressions passed as arguments to a function, e.g. in foo(ls())
the expression passed is ls()
, are evaluated lazily, only if and when needed by the implementation of the called function.
delayedAssign
是一个低级函数,对于R用户/程序员可见,但实际上仅用于延迟加载程序包,而在用户程序中则不需要. delayedAssign
允许指定一个表达式来计算变量的值;仅当/首次读取变量时,计算才会延迟进行.
delayedAssign
is a low-level function, visible to R users/programmers, but it really is only used for lazy loading of packages and should not be needed in user programs. delayedAssign
allows to specify an expression to compute the value of a variable; the computation will happen lazily only if/when the variable is read the first time.
因此,要回答这个问题,R中的赋值始终是惰性"的,因为使用了写时复制机制.赋值右侧的计算也可以是懒惰的(使用delayedAssign
),但是用户程序不应该需要/不使用它.
So, to answer the question, an assignment in R is always ''lazy'' in that the copy-on-write mechanism is used. The computation of the right-hand-side of the assignment can be also lazy (using delayedAssign
), but that should not be needed/used by user programs.
我认为对于变量的重命名",不需要使用delayedAssign
(因为未计算右侧).这只会使情况变得更加复杂,并且由于记账delayedAssign
必须这样做,因此可能会产生性能开销.如果必须重命名变量,我只会使用普通分配.
I think for the ''renaming'' of variables, there is no need to use delayedAssign
(because the right-hand-side is not computed). It only makes the situation more complex and there will likely be performance overhead due to the book-keeping delayedAssign
has to do. I would just use ordinary assignment if I had to rename variables.
为了代码清晰,我也会尽可能避免从环境中删除变量,甚至避免从函数分配给全局环境,例如我只是创建一个新列表,然后将新的绑定(变量)插入其中.
For code clarity, I would also whenever possible try to avoid deleting variables from environments and even assigning from a function into the global environment, e.g. I would just create a new list and insert the new bindings (variables) into it.
已经提到了写时复制机制,对于GNU-R中的当前实现,所描述的任何解决方案都可能导致内存复制,如果不重命名变量,则不需要复制.在R级别上无法避免这种情况.
Having mentioned the copy-on-write mechanism, with the current implementation in GNU-R, any of the described solutions will potentially cause memory copying that would not be necessary had the variables not been renamed. There is no way to avoid this at R level.
这篇关于R中的惰性评估–分配会受到影响吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!