开发者

How can I create a custom assignment using a replacement function?

开发者 https://www.devze.com 2023-04-06 09:59 出处:网络
I have defined a function called once as follows: once <- function(x, value) { xname <- deparse(substitute(x))

I have defined a function called once as follows:

once <- function(x, value) {
    xname <- deparse(substitute(x))
    if(!exists(xname)) {
        assign(xname, value, env=parent.frame())
    }
    invisible()
}

The idea is that value is time-consuming to evaluate, and I only want to assign i开发者_开发问答t to x the first time I run a script.

> z
Error: object 'z' not found
> once(z, 3)
> z
[1] 3

I'd really like the usage to be once(x) <- value rather than once(x, value), but if I write a function once<- it gets upset that the variable doesn't exist:

> once(z) <- 3
Error in once(z) <- 3 : object 'z' not found

Does anyone have a way around this?

ps: is there a name to describe functions like once<- or in general f<-?


If you are willing to modify your requirements slightly to use square brackets rather than parentheses then you could do this:

once <- structure(NA, class = "once")
"[<-.once" <- function(once, x, value) {
    xname <- deparse(substitute(x))
    pf <- parent.frame()
    if (!exists(xname, pf)) assign(xname, value, pf)
    once
}


# assigns 3 to x (assuming x does not currently exist)
once[x] <- 3
x # 3

# skips assignment (since x now exists)
once[x] <- 4
x # 3


As per item 3.4.4 in the R Language Reference, something like a names replacement is evaluated like this:

 `*tmp*` <- x
 x <- "names<-"(`*tmp*`, value=c("a","b"))
 rm(`*tmp*`)

This is bad news for your requirement, because the assignment will fail on the first line (as x is not found), and even if it would work, your deparse(substitute) call will never evaluate to what you want it to.

Sorry to disappoint you

0

精彩评论

暂无评论...
验证码 换一张
取 消