[EDIT:. Das Problem Auffordern diese Abhilfe, da R 3.1.0 behoben wurde]R: Wie kann eine Funktion variable Argumente mit Ellipsen (...) akzeptieren, ohne sie in den Speicher zu kopieren?
Ich wurde an anderer Stelle gebeten, dies als selbst beantworteten Frage zu stellen.
Wenn eine R-Funktion eine beliebige Anzahl von Parametern durch die Auslassungs Argumente akzeptiert, der gemeinsame Weg, um sie für den Zugriff verwendet list(...)
:
f <- function(...) {
dots <- list(...)
# Let's print them out.
for (i in seq_along(dots)) {
cat(i, ": name=", names(dots)[i], "\n", sep="")
print(dots[[i]])
}
}
> f(10, a=20)
1: name=
[1] 10
2: name=a
[1] 20
jedoch R (ab v3.0.2) tief kopiert alle list
Elemente:
> x <- 10
> .Internal(inspect(x))
@10d85ca68 14 REALSXP g0c1 [MARK,NAM(2),TR] (len=1, tl=0) 10
> x2 <- x
> .Internal(inspect(x2)) # Not copied.
@10d85ca68 14 REALSXP g0c1 [MARK,NAM(2),TR] (len=1, tl=0) 10
> y <- list(x)
> .Internal(inspect(y[[1]])) # x was copied to a different address:
@10dd45e88 14 REALSXP g0c1 [MARK,NAM(1),TR] (len=1, tl=0) 10
> z <- list(y)
> .Internal(inspect(z)) # y was deep-copied:
@10d889ed8 19 VECSXP g0c1 [MARK,NAM(1)] (len=1, tl=0)
@10d889f38 19 VECSXP g0c1 [MARK,TR] (len=1, tl=0)
@10d889f68 14 REALSXP g0c1 [MARK] (len=1, tl=0) 10
Sie können dies auch mit tracemem
überprüfen, ob Sie Speicherprofilerstellung aktiviert haben.
Sie haben also große Objekte in einem list
gespeichert? Kopiert. Übergeben Sie sie in jede Funktion, die list(...)
innen aufruft? Kopiert:
> g <- function(...) for (x in list(...)) .Internal(inspect(x))
> g(z) # Copied.
@10dd45e58 19 VECSXP g0c1 [] (len=1, tl=0)
@10dd35fa8 19 VECSXP g0c1 [] (len=1, tl=0)
@10dd36068 19 VECSXP g0c1 [] (len=1, tl=0)
@10dd36158 14 REALSXP g0c1 [] (len=1, tl=0) 10
> g(z) # ...copied again.
@10dd32268 19 VECSXP g0c1 [] (len=1, tl=0)
@10d854c68 19 VECSXP g0c1 [] (len=1, tl=0)
@10d8548d8 19 VECSXP g0c1 [] (len=1, tl=0)
@10d8548a8 14 REALSXP g0c1 [] (len=1, tl=0) 10
Noch nicht entsetzt? Versuchen Sie grep -l "list(\.\.\.)" *.R
in R-Bibliothek Quellen. Mein Favorit ist mapply
/Map
, von dem ich routinemäßig GBs von Daten anrief und mich fragte, warum der Speicher knapp wurde. Mindestens lapply
ist in Ordnung.
Also, wie kann ich eine variadic Funktion mit ...
Argumente schreiben und vermeiden, sie zu kopieren?
Ich hatte das Kopieren von Elementen beim Umgang mit Listen bemerkt, aber nicht bemerkt, dass es ein neues "Feature" war. – BrodieG
Ich glaube nicht, dass es neu ist. Ich habe die Version nur für den Fall notiert, dass sie sich in der Zukunft ändert. – codeola
Und in der Tat ist es für 3.1.0 – hadley