Search code examples
r

Determining as to whether the function call is stored in a variable


Bear with me if this is a duplicate, but cannot find anything so far: In R is there a way one can be able to tell whether a function call output is stored in a variable or not?

example:

fun <- function(x, y){
  # what can I do here to print TRUE/FALSE
 sum(x, y)
}
a <- fun(1, 2) # TRUE -- the function call is stored in a variable a
fun(1, 2) # FALSE -- not stored in a variable
b <- fun(1, 2) # TRUE -- stored in a variable `b`

Solution

  • Regarding terminology what the question is referring to as the call is actually the return value.

    1) Now, define fun to assign the return value to the variable whose name is the first argument. Below the the default value of ".tmp" has been given to name so that if no name is specified the result is placed in a variable of that name in the env environment.

    fun <- function(name = ".tmp", x, y, env = parent.frame()) {
       assign(name, sum(x, y), env)
    }
    
    fun("a", 1, 2); a
    ## [1] 3
    
    fun("b", 1, 2); b
    ## [1] 3
    
    fun(x = 1, y = 2); .tmp
    ## [1] 3
    

    2) Another possibility is to always place it in .tmp This stores .tmp in the environment of the caller. Use env = .GlobalEnv to store it in the global environment should that be different from the parent frame.

    fun2 <- function(x, y, env = parent.frame()) {
       assign(".tmp", sum(x, y), env)
    }
    
    fun2(1, 2); .tmp
    ## [1] 3
    

    Note that if we assign the return value of fun2 to a variable that it will actually point to the same piece of memory as .tmp so that there are not two copies. Try this:

    library(pryr)
    a <- fun2(1, 2)
    
    address(a)
    ## [1] "0x28c2c03f178"
    
    address(.tmp)
    ## [1] "0x28c2c03f178"
    

    R has copy-on-modify semantics so if we were to modify one of those two objects a copy would occur at that point but as long as we don't there is no extra memory overhead.

    3) We could use object oriented programming. Create a proto object p with method fun which stores the result in p$result.

    library(proto)
    
    p <- proto(fun = function(., x, y) .$result <- sum(x, y))
    
    p$fun(1, 2)
    p$result
    ## [1] 3
    

    4) We could define a replacement function which takes an empty list, L, and a list of arguments and stores the result of the calculation in the result component of the empty list. Note that L must be created before we run the calculation.

    `fun<-` <- function(x, value) {
       x$result <- do.call("sum", value)
       x
    }
    
    L <- list()
    fun(L) <- list(1, 2)
    L$result
    ## [1] 3