将对象传递给函数而不更改时将其复制 [英] Pass an object to a function without copying it on change

查看:63
本文介绍了将对象传递给函数而不更改时将其复制的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果将对象x传递给对其进行修改的函数f,则R将在f的环境内创建x的修改后的本地副本,而不是更改原始对象(由于该副本) -on-on-change原则).但是,我遇到的情况是x很大,一旦传递给f就不需要了,所以我想避免在调用f后存储x的原始副本.有什么聪明的方法可以做到这一点吗?

If an object x is passed to a function f that modifies it R will create a modified local copy of x within f's environment, rather than changing the original object (due to the copy-on-change principle). However, I have a situation where x is very big and not needed once it has been passed to f, so I want to avoid storing the original copy of x once f is called. Is there a clever way to achieve this?

f是一个未知的功能,可能由不太聪明的用户提供.

f is an unknown function to be supplied by a possibly not very clever user.

到目前为止,我最好的解决方法是将x包裹在函数forget中,该函数对称为yx进行新的本地引用,删除工作空间中的原始引用,然后传递新的参考.问题是我不确定它是否能完成我想要的工作,并且只能在globalenv()中工作,这在我当前的情况下是一个大问题.

The best I have so far is to wrap x in a function forget that makes a new local reference to x called y, removes the original reference in the workspace, and then passes on the new reference. The problem is that I am not certain it accomplish what I want and it only works in globalenv(), which is a deal breaker in my current case.

forget <- function(x){
    y <- x
    # x and y now refers to the same object, which has not yet been copied
    print(tracemem(y))
    rm(list=deparse(substitute(x)), envir=globalenv())
    # The outside reference is now removed so modifying `y`
    # should no longer result in a copy (other than the
    # intermediate copy produced in the assigment)
    y
}

f <- function(x){
    print(tracemem(x))
    x[2] <- 9000.1
    x
}

这里是调用上述函数的示例.

Here is an example of calling the above function.

> a <- 1:3
> tracemem(a)
[1] "<0x2ac1028>"
> b <- f(forget(a))
[1] "<0x2ac1028>"
[1] "<0x2ac1028>"
tracemem[0x2ac1028 -> 0x2ac1e78]: f 
tracemem[0x2ac1e78 -> 0x308f7a0]: f 
> tracemem(b)
[1] "<0x308f7a0>"
> b
[1]    1.0 9000.1    3.0
> a
Error: object 'a' not found

底线

我正在做自己希望做的事情,还有更好的方法吗?

Bottom line

Am I doing what I hope I am doing and is there a better way to do it?

推荐答案

(1)环境您可以为此使用环境:

(1) Environments You can use environments for that:

e <- new.env()
e$x <- 1:3
f <- function(e) with(e, x <- x + 1)
f(e)
e$x

(2)参考类,或者由于参考类会自动使用环境,因此会使用以下类:

(2) Reference Classes or since reference classes automatically use environments use those:

E <- setRefClass("E", fields = "x",
    methods = list(
        f = function() x <<- x + 1
    )
)
e <- E$new(x = 1:3)
e$f()
e$x

(3)个原型对象也使用环境:

library(proto)
p <- proto(x = 1:3, f = function(.) with(., x <- x + 1))
p$f()
p$x

添加:原始解决方案

已更新:为了与问题保持一致,将函数名称更改为f.

UPDATED: Changed function name to f for consistency with question.

这篇关于将对象传递给函数而不更改时将其复制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆