Skip to content
Prev 13962 / 398502 Next

Avoiding deep copies

On Tue, Oct 02, 2001 at 02:21:51PM +0200, Johann Petrak wrote:
There are two (useful) types of object that are passed by reference in
R: environments and external pointers.  External pointers are useful
for managing data allocated at the C level.  Environments are useful
for doing this sort of thing at the R level.  For example, if you
define, say,

new.ref <- function(value = NULL) {
    ref <- new.env()
    assign("value", value, env = ref)
    ref
}

ref.value <- function(ref) get("value", env = ref)

"ref.value<-" <- function(ref, value) {
    assign("value", value, env = ref)
    ref
}

then

r <- new.ref(<data that should not be copied>)

produces a reference object that will not be deep copied, and

s <- r

makes s another name for that reference, so that ref.value(s) <- <new value>
changes the value returned by ref.value(r):
[1] 1
[1] 2
[1] 2

A slightly fancier version would wrap the environment in a list and
attach a class to it, something like

new.ref <- function(value = NULL) {
    ref <- list(env = new.env())
    class(ref) <- "refObject"
    assign("value", value, env = ref$env)
    ref
}

is.refObject <- function(r) inherits(r, "refObject")

print.refObject <- function(r) cat("<reference>\n")

ref.value <- function(ref) {
    if (! is.refObject(ref)) stop("not a refObject")
    get("value", env = ref$env)
}

"ref.value<-" <- function(ref, value) {
    if (! is.refObject(ref)) stop("not a refObject")
    assign("value", value, env = ref$env)
    ref
}

Then
<reference>
Error in ref.value(3) : not a refObject


We've talked about adding something like this off and on but have not
gotten around to it yet.

luke
Message-ID: <20011002090438.A21473@nokomis.stat.umn.edu>
In-Reply-To: <3BB9B15F.2090604@ai.univie.ac.at>; from johann@ai.univie.ac.at on Tue, Oct 02, 2001 at 02:21:51PM +0200