2

I wonder if R functions can know the name of the variable their result is assigned to.

e.g.

selfaware_squared <- function(x) {
  cat("Assigning square to variable name '", some_magic, "'.")
  return(x^2)
}

> a <- selfaware_squared(2)
Assigning square to variable name ' a '.
mzuba
  • 1,226
  • 1
  • 16
  • 33

2 Answers2

3

sys.call is an option if you are using assign to do the assignment. It allows you to retrieve outer function calls from inner ones:

f <- function(x) {
  cl <- sys.call(-1L)
  if (!is.null(cl) && cl[[1L]] == "assign") {
    nm <- match.call(assign, cl)$x
    if (is.character(nm) && length(nm) > 0L) {
      cat("assigning square of", sQuote(deparse(substitute(x))),
          "to variable", sQuote(nm[1L]), "\n")
    }
  }
  x * x
}

assign("y1", f(10)); y1
## assigning square of ‘10’ to variable ‘y1’ 
## [1] 100

assign("y2", f(1:10)); y2
## assigning square of ‘1:10’ to variable ‘y2’ 
## [1]   1   4   9  16  25  36  49  64  81 100

assign("y3", f(pi)); y3 
## assigning square of ‘pi’ to variable ‘y3’
## [1] 9.869604

assign("y4", f(sqrt(pi))); y4 
## assigning square of ‘sqrt(pi)’ to variable ‘y4’
## [1] 3.141593

Unfortunately, this approach doesn't extend to <-, because it is a special primitive, not a closure (compare typeof(`<-`) and typeof(assign)). Calls to special primitives don't appear on the call stack, so there would be nothing for sys.call to retrieve. As a result, y <- f(10) assigns the value 100 to y without generating any output.

Mikael Jagan
  • 9,012
  • 2
  • 17
  • 48
1

I think the only way the function could know the name of where it's output is being assigned is if it's provided as an input to the function. So for example you could make that an input and use assign() inside the function (although this should probably done with great care).

selfaware_squared <- function(x, nm) {
  cat("Assigning square to variable name '", nm, "'.")
  assign(x = nm, value = x^2, envir = globalenv())
}

selfaware_squared(2, "a")
#> Assigning square to variable name ' a '.

a
#> [1] 4

Created on 2022-01-27 by the reprex package (v2.0.1)

Also see discussion of this topic here.

Dan Adams
  • 4,971
  • 9
  • 28