你可以在R中传递参考吗?

Pie*_*rre 66 oop r parameter-passing pass-by-reference

你能用"R"通过参考吗?例如,在以下代码中:

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
Run Code Online (Sandbox Code Playgroud)

输出是

> 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"
Run Code Online (Sandbox Code Playgroud)

但我希望如此

> 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"
Run Code Online (Sandbox Code Playgroud)

可能吗 ?

dou*_*oug 54

.

赋值语句中的对象是不可变的.R将复制对象而不仅仅是参考.

> 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
Run Code Online (Sandbox Code Playgroud)

(附带条件:上述陈述适用于R 原语,例如矢量,矩阵),也适用于函数 ; 我不能肯定地确定它是否适用于所有 R对象 - 只是大部分对象,以及绝大多数最常用的对象.)

如果您不喜欢这种行为,可以在R套餐的帮助下选择退出.例如,有一个名为R.oo的R包允许您模仿传递引用行为; R.oo可以在CRAN上找到.

  • 我发现这个"不".相反,好吧,*粗体*,因为许多软件包似乎允许通过引用传递,[以及](/sf/answers/791049521/)`Rcpp`接口与C/C++. (9认同)
  • 另请参阅`mutatr`和`proto`包. (5认同)

Ari*_*man 42

请注意,如果您希望仅使用pass-by-reference来避免复制未修改的对象的性能影响(在常量引用的其他语言中很常见),R会自动执行此操作:

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
Run Code Online (Sandbox Code Playgroud)

  • 非常有帮助知道!我还补充说,这似乎只适用于data.frames.矩阵/数组总是按值传递,正如我刚刚在Rprof输出上刮了几个小时后才知道的那样. (6认同)
  • 现在在我的笔记本电脑上重新运行:现在所有时间都是一样的(是五年前的一半) (2认同)

Rap*_*ter 23

正如一些人之前指出的那样,这可以通过使用类的对象来完成environment.存在一种基于environments 的正式方法.它被称为参考类,让事情变得非常简单.检查?setRefClass主条目帮助页面.它还描述了如何使用带有Reference Classes的正式方法.

setRefClass("MyClass",
    fields=list(
        name="character"
    )
)

instance1 <- new("MyClass",name="Hello1")
instance2 <- new("MyClass",name="Hello2")

array = c(instance1,instance2)

instance1$name <- "World!"
Run Code Online (Sandbox Code Playgroud)

产量

> 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"
Run Code Online (Sandbox Code Playgroud)


teu*_*cer 18

environments 可以通过引用.要使用它们,基本上每当您创建对象时,您都需要创建一个环境槽.但我认为这很麻烦.看看 S4的Pass参考.指针并在R中通过引用传递


Kyl*_*ndt 5

R现在有一个库,允许您使用引用进行OOP.请参阅ReferenceClasses,它是方法包的一部分.