[R] Avoiding deep copies

Luke Tierney luke at nokomis.stat.umn.edu
Tue Oct 2 16:04:38 CEST 2001


On Tue, Oct 02, 2001 at 02:21:51PM +0200, Johann Petrak wrote:
> Is it correct that there is no way of avoiding deep copying
> of data structures? Or asked from a different perspective,
> is it true that there are no pointers? :)
> (not that I am a fan of pointer, they just let me
> decide when to do deep copy on my own when the
> memory manager doesnt do it for me :) )
> 
> I was considering writing code in R that would need
> the internal representation of complex graph structures
> where several nodes in the graph point to the same
> huge array of data.
> Now, obviously one cannot just do something like
> attr(thenode,"mydatavec")<-thedatavec or
> thenode$mydatavec<-thedatavec
> since all the data in thedatavec will be copied
> with this assignment.
> Are there commonly accepted/used workarounds?
> 
> Johann
> 

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):

> r <- new.ref(1)
> ref.value(r)
[1] 1
> s<-r
> ref.value(s) <- 2
> ref.value(s)     
[1] 2
> ref.value(r)
[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

> r <- new.ref(1)
> r
<reference>
> ref.value(3)
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

-- 
Luke Tierney
University of Minnesota                      Phone:           612-625-7843
School of Statistics                         Fax:             612-624-8868
313 Ford Hall, 224 Church St. S.E.           email:      luke at stat.umn.edu
Minneapolis, MN 55455 USA                    WWW:  http://www.stat.umn.edu
-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
r-help mailing list -- Read http://www.ci.tuwien.ac.at/~hornik/R/R-FAQ.html
Send "info", "help", or "[un]subscribe"
(in the "body", not the subject !)  To: r-help-request at stat.math.ethz.ch
_._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._



More information about the R-help mailing list