Können Sie mit "R" verweisen? Zum Beispiel im folgenden Code:
setClass("MyClass",
representation(
name="character"
))
instance1 <-new("MyClass",name="Hello1")
instance2 <-new("MyClass",name="Hello2")
array = c(instance1,instance2)
instance1
array
instance1@name="World!"
instance1
array
die Ausgabe ist
> instance1
An object of class “MyClass”
Slot "name":
[1] "World!"
> array
[[1]]
An object of class “MyClass”
Slot "name":
[1] "Hello1"
[[2]]
An object of class “MyClass”
Slot "name":
[1] "Hello2"
aber ich wünschte es wäre
> instance1
An object of class “MyClass”
Slot "name":
[1] "World!"
> array
[[1]]
An object of class “MyClass”
Slot "name":
[1] "World!"
[[2]]
An object of class “MyClass”
Slot "name":
[1] "Hello2"
ist es möglich ?
r
oop
parameter-passing
pass-by-reference
Pierre
quelle
quelle
Antworten:
Nein .
Objekte in Zuweisungsanweisungen sind unveränderlich. R kopiert das Objekt und nicht nur die Referenz.
> v = matrix(1:12, nrow=4) > v [,1] [,2] [,3] [1,] 1 5 9 [2,] 2 6 10 [3,] 3 7 11 [4,] 4 8 12 > v1 = v > v1[,1] # fetch the first column [1] 1 2 3 4
( Vorbehalt : Die obige Aussage gilt für R- Primitive , z. B. Vektoren, Matrizen) und auch für Funktionen ; Ich kann nicht mit Sicherheit sagen, ob dies für alle R-Objekte gilt - nur für die meisten von ihnen sowie für die überwiegende Mehrheit der am häufigsten verwendeten.)
Wenn Ihnen dieses Verhalten nicht gefällt, können Sie es mithilfe eines R-Pakets deaktivieren. Zum Beispiel gibt es ein R-Paket namens R.oo , mit dem Sie das Pass-by-Reference-Verhalten nachahmen können. R.oo ist auf CRAN verfügbar .
quelle
mutatr
undproto
Pakete.mutatr
scheint nicht unterstützt und nicht dokumentiert..Call
Wrapper eines C ++ übergeben?Rcpp
Schnittstelle zu C / C ++ zu ermöglichen scheinen .Beachten Sie, dass R dies automatisch tut, wenn Sie die Referenzübergabe verwenden möchten, um die Auswirkungen des Kopierens eines Objekts, das nicht geändert wurde (wie es in anderen Sprachen mit konstanten Referenzen üblich ist), auf die Leistung zu vermeiden:
n <- 10^7 bigdf <- data.frame( x=runif(n), y=rnorm(n), z=rt(n,5) ) myfunc <- function(dat) invisible(with( dat, x^2+mean(y)+sqrt(exp(z)) )) myfunc2 <- function(dat) { x <- with( dat, x^2+mean(y)+sqrt(exp(z)) ) invisible(x) } myfunc3 <- function(dat) { dat[1,1] <- 0 invisible( with( dat, x^2+mean(y)+sqrt(exp(z)) ) ) } tracemem(bigdf) > myfunc(bigdf) > # nothing copied > myfunc2(bigdf) > # nothing copied! > myfunc3(bigdf) tracemem[0x6e430228 -> 0x6b75fca0]: myfunc3 tracemem[0x6b75fca0 -> 0x6e4306f0]: [<-.data.frame [<- myfunc3 tracemem[0x6e4306f0 -> 0x6e4304f8]: [<-.data.frame [<- myfunc3 > > library(microbenchmark) > microbenchmark(myfunc(bigdf), myfunc2(bigdf), myfunc3(bigdf), times=5) Unit: milliseconds expr min lq median uq max 1 myfunc2(bigdf) 617.8176 641.7673 644.3764 683.6099 698.1078 2 myfunc3(bigdf) 1052.1128 1134.0822 1196.2832 1202.5492 1206.5925 3 myfunc(bigdf) 598.9407 622.9457 627.9598 642.2727 654.8786
quelle
matrix
,array
undtibble
. Hat sich das Verhalten geändert, seit Sie Ihren Kommentar gepostet haben, oder irre ich mich?Wie bereits erwähnt, kann dies über Klassenobjekte erfolgen
environment
. Es gibt einen formalen Ansatz, der auf der Verwendung vonenvironment
s aufbaut. Es heißt Referenzklassen und macht es Ihnen wirklich einfach. Suchen Sie?setRefClass
nach der Hilfeseite für den Haupteintrag. Außerdem wird beschrieben, wie formale Methoden mit Referenzklassen verwendet werden.Beispiel
setRefClass("MyClass", fields=list( name="character" ) ) instance1 <- new("MyClass",name="Hello1") instance2 <- new("MyClass",name="Hello2") array = c(instance1,instance2) instance1$name <- "World!"
Ausgabe
> instance1 Reference class object of class "MyClass" Field "name": [1] "World!" > array [[1]] Reference class object of class "MyClass" Field "name": [1] "World!" [[2]] Reference class object of class "MyClass" Field "name": [1] "Hello2"
quelle
Pass-by-Reference ist für
environment
s möglich . Um sie zu verwenden, müssten Sie grundsätzlich jedes Mal, wenn Sie ein Objekt erstellen, auch einen Umgebungssteckplatz erstellen. Aber ich denke, dass es umständlich ist. Schauen Sie sich Pass by Reference für S4 an. und Zeiger und Verweis in R.quelle
R verfügt jetzt über eine Bibliothek, mit der Sie OOP mithilfe von Referenzen ausführen können. Siehe ReferenceClasses, das Teil des Methodenpakets ist.
quelle
Tatsächlich emuliert das R.oo- Paket das Pass-by-Reference-Verhalten mithilfe von Umgebungen.
quelle
Wie bereits erwähnt, ist dies für S4-Klassen nicht möglich. Aber R bietet jetzt die Möglichkeit mit der R6- Bibliothek, die als Referenzklassen bezeichnet wird . Siehe offizielle Dokumentation
quelle
Zusätzlich zu den anderen Antworten hier, die Ihr Objekt tatsächlich als Referenz übergeben (
environment
Objekte und Referenzklassen), sind Sie, wenn Sie aus syntaktischen Gründen nur an Call-by-Reference interessiert sind (dh es macht Ihnen nichts aus, wenn Ihre Daten darin kopiert werden), Sie könnte dies emulieren, indem der endgültige Wert bei der Rückgabe der externen Variablen zugewiesen wird:byRef <- function(..., envir=parent.frame(), inherits=TRUE) { cl <- match.call(expand.dots = TRUE) cl[c(1, match(c("envir", "inherits"), names(cl), 0L))] <- NULL for (x in as.list(cl)) { s <- substitute(x) sx <- do.call(substitute, list(s), envir=envir) dx <- deparse(sx) expr <- substitute(assign(dx, s, envir=parent.frame(), inherits=inherits)) do.call(on.exit, list(expr, add=TRUE), envir=envir) } }
Dann können wir "Call-by-Reference" -Argumente deklarieren:
f <- function(z1, z2, z3) { byRef(z1, z3) z1 <- z1 + 1 z2 <- z2 + 2 z3 <- z3 + 3 c(z1, z2, z3) } x1 <- 10 x2 <- 20 x3 <- 30 # Values inside: print(f(x1, x2, x3)) # [1] 11 22 33 # Values outside: print(c(x1, x2, x3)) # [1] 11 20 33
Beachten Sie, dass Sie die noch nicht geänderten Werte von außen erhalten , wenn Sie auf die "by-reference" -Variablen mit ihren externen Namen (
x1
,x3
) an einer beliebigen Stelle innerhalb der Funktion zugreifen . Außerdem behandelt diese Implementierung nur einfache Variablennamen als Argumente, sodass indizierte Argumente wief(x[1], ...)
diese nicht funktionieren (obwohl Sie dies wahrscheinlich mit einer etwas aufwendigeren Ausdrucksmanipulation implementieren könnten, um die Begrenzung zu umgehenassign
).quelle
Zusätzlich zu den anderen Vorschlägen können Sie auch C / C ++ - Funktionen schreiben, die ihre Argumente als Referenz verwenden und an Ort und Stelle arbeiten , und sie dank
Rcpp
(unter anderem) direkt in R aufrufen . Siehe insbesondere diese Antwort .quelle