How to create a custom assignment using the replace function?

I 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 takes a lot of time to evaluate, and I only want to assign it x when the script is first run.

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

I would really like the use to be once(x) <- value , and not once(x, value) , but if I write the function once<- , it will be frustrated that the variable does not 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 for describing functions like once<- or even f<- ?

+4
source share
2 answers

According to clause 3.4.4, in the R language reference, something like a name change is evaluated as follows:

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

This is bad news for your requirement, because the assignment will not be executed on the first line (since x is not found), and even if it works, your deparse(substitute) call will never evaluate what you want.

Sorry to disappoint you.

+6
source

If you want to change your requirements a bit to use square brackets rather than parentheses, you can 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 
+7
source

All Articles