R如何处理函数调用中的对象?

R如何处理函数调用中的对象?,r,object,R,Object,我有Java和Python的背景,最近正在学习R 今天我发现R处理对象的方式似乎与Java和Python完全不同 例如,以下代码: x <- c(1:10) print(x) sapply(1:10,function(i){ x[i] = 4 }) print(x) 但是我希望第二行输出都是'4',因为我在sappy函数中修改了向量 这是否意味着R在函数调用中复制对象,而不是引用对象?是的,你说得对。检查R语言定义: 好吧,在您尝试修改数据之前,R

我有Java和Python的背景,最近正在学习R

今天我发现R处理对象的方式似乎与Java和Python完全不同

例如,以下代码:

x <- c(1:10)
print(x)
sapply(1:10,function(i){
            x[i] = 4
        })
print(x)
但是我希望第二行输出都是'4',因为我在sappy函数中修改了向量


这是否意味着R在函数调用中复制对象,而不是引用对象?

是的,你说得对。检查R语言定义:


好吧,在您尝试修改数据之前,R不会真正复制数据,因此遵循语义。

您需要将sapply的输出分配给一个对象,否则它就会消失。(实际上您可以恢复它,因为它也被分配到
.Last.value


x
x
是在全局环境中定义的,而不是在您的函数中定义的

如果您试图在函数中修改非本地对象,如
x
,则R会复制该对象并修改该副本,因此每次运行匿名函数时,都会复制
x
,其第i个组件设置为4。当函数退出时,生成的副本将永远消失。未修改原始的
x


如果我们编写
x[i]匿名函数中的
x
不是
x
全局环境(您的工作区)。它是匿名函数本地的
x
的副本。说R在函数调用中复制对象并不是那么简单;如果可以,R将努力不复制,尽管一旦你修改了某些东西,R必须复制对象

正如@DWin指出的,这个被修改的
x
复制版本是
sapply()
调用返回的,您声称的输出不是我得到的:

> x <- c(1:10)
> print(x)
 [1]  1  2  3  4  5  6  7  8  9 10
> sapply(1:10,function(i){
+             x[i] = 4
+         })
 [1] 4 4 4 4 4 4 4 4 4 4
> print(x)
 [1]  1  2  3  4  5  6  7  8  9 10
如果您了解这类内容,请阅读手册,其中涵盖了R中引擎盖下发生的许多细节。

如果您想从函数中更改“全局”对象,则可以使用非局部赋值

x <- c(1:10)
# [1]  1  2  3  4  5  6  7  8  9 10
print(x)
sapply(1:10,function(i){
            x[i] <<- 4
        })
print(x)
# [1] 4 4 4 4 4 4 4 4 4 4

x谢谢安纳托利!但是,如果复制的数据真的很大,复制过程会花费太多的时间和内存吗?或者它实际上并不复制数据,只是在函数调用结束时抵消修改效果?有一个副本,但函数内部的“x”与函数外部的“x”不是同一个对象。有一些环境,调用环境中有一个x,函数环境中有一个不同的x。只有通过分配结果,才能在调用环境中看到更改。对不起,这并不能回答问题,只是让人困惑。现在是我困惑了。OP创建了一个4的向量,然后什么也没做。如果他想改变“x”,他需要使用赋值操作。我想我已经准确地回答了这个问题。你似乎在暗示
v是的,我在暗示v,但
=
只是返回4,而不是承诺
x[I]
;这样就相当于
xThanks!但是为什么不用R编写这样的代码呢?是否存在一些潜在的风险或只是一个惯例?我认为在其他语言中修改函数中的全局对象是很正常的。在函数语言中,函数不能有副作用。R没有那么严格,但R函数限制副作用仍然是正确的。最好按照预期的方式使用,而不是试图用另一种语言写作。有几个对象系统(S3、S4、参考类)。S3是最常用的。S4要复杂得多。参考类是最近增加的。特别是,您可能希望探索参考类。还有一些用户提供的包提供了不同的范例:proto和R.oo(可能还有其他的)。@Spirit Plus您可以使用
parent.frame(3)
而不是
.GlobalEnv
将x存储在运行sapply的闭包中,这样会更安全。(为什么是3?1-匿名功能框架,2-蓝宝石框架,3-蓝宝石外壳)Oops-我在几个小时前(英国时间早上)写了这篇文章,但肯定是偏离了方向,没有点击提交按钮。
e <- environment()
sapply(1:10, function(i) e$x[i] <- 4)
sapply(1:10, function(i, e) e$x[i] <- 4, e = environment())
x <- sapply(1:10, function(i) 4)
library(proto)

p <- proto(x = 1:10, f = function(., i) .$x[i] <- 4)

for(i in seq_along(p$x)) p$f(i)
p$x
> x <- c(1:10)
> print(x)
 [1]  1  2  3  4  5  6  7  8  9 10
> sapply(1:10,function(i){
+             x[i] = 4
+         })
 [1] 4 4 4 4 4 4 4 4 4 4
> print(x)
 [1]  1  2  3  4  5  6  7  8  9 10
> a <- new.env()
> a
<environment: 0x1af2ee0>
> b <- 4
> assign("b", b, env = a)
> a$b
[1] 4
> c <- a ## copy the environment to `c`
> assign("b", 7, env = c) ## assign something to `b` in env `c`
> c$b ## as expected
[1] 7
> a$b ## also changed `b` in `a` as `a` and `c` are actually the same thing
[1] 7
x <- c(1:10)
# [1]  1  2  3  4  5  6  7  8  9 10
print(x)
sapply(1:10,function(i){
            x[i] <<- 4
        })
print(x)
# [1] 4 4 4 4 4 4 4 4 4 4