0

Say that I have the following function:

myfun <- function(x){
     assignee <- get_assignee_name()
     message(paste0("output assigned to ",assignee,"!"))
     x
   }
my_var <- myfun(7)

output assigned to my_var!

I am looking for something that does the job of get_assignee_name() above. It should be a function or a few lines of code that is called from inside a function, it examines the call that it occurs inside of and returns the object that is being assigned to as a character, if one exists. So in the example

answer <- myfun(10)

the message "output assigned to answer!" should appear.

I am aware that this seems unnecessarily complicated, but it is just an example to demonstrate the point for a more complicated use case. I am also aware that of ways around this involving passing the variable name into the function as a parameter and then calling assign. This won't solve the problem in this case, where this should be transparent to the user

michael
  • 153
  • 1
  • 11
  • 1
    @jay.sf I don't think they want to translate numbers to words, but print out what was assigned to a variable, in their example 10 (or ten). – zx8754 Nov 08 '19 at 11:50
  • Not sure if I got the question entirely, but I think the variable assignment takes place after the function returned, therefore the variable name (used for the return value) is unknown until the function returns and assigns the value. Otherwise, this maybe helps: https://stackoverflow.com/questions/6034655/convert-string-to-a-variable-name/16703574 – holzben Nov 08 '19 at 12:01
  • 1
    @holzben that makes sense about the function being called and completed in isolation from the assignment, though at the same time I can imagine a parse tree that the function call would be a part of. I'm imagining something like `match.call()` but that contains the object of assignment as well. – michael Nov 08 '19 at 12:09
  • 1
    Doesn't seem possible. How is a function supposed to know the intentions of the caller? It returns a value. The caller decides to do something with that value, which is *not* always to assign it to a variable. Possibly an XY problem -- what are you trying to accomplish? – John Coleman Nov 08 '19 at 12:18
  • @JohnColeman This is a problem that pops up every few months in different contexts, so I am looking for the generel solution rather than a specific alternative. In this case, I want to make the output of the calling function immutable. lockBinding looks like it might do the trick, but it needs to know the assignee variable in order to lock the symbol. Again though, I am more interested in the general solution if one exists rather than the case i just described. – michael Nov 08 '19 at 12:25
  • 1
    If it were possible to write functions like that, the name of the assignee would function as a hidden input, and the function itself would have a context-dependent semantics. Sounds like a nightmare to debug. R's nonstandard evaluation already leads to debugging problems at times. Making it even less standard is unlikely to lead to better code. – John Coleman Nov 08 '19 at 12:37
  • @JohnColeman That's not so. You can access the call stack. The issue is that `<-` is not part of the call stack. – Roland Nov 08 '19 at 13:44

1 Answers1

3

This is not possible because <- is a primitive and quite special function. It is not part of the call stack. You would need to use assign instead:

myfun <- function(x){
  assignee <- sys.call(1)
  if (assignee[[1]] == quote(assign)) 
    message(paste0("output assigned to ",assignee[[2]],"!"))
  x
}
assign("my_var", myfun(7))
#output assigned to my_var!
my_var
#[1] 7

However, I suggest you reconsider how you approach your actual issue.

Roland
  • 127,288
  • 10
  • 191
  • 288
  • Interesting (+1). Perhaps you could do some deep magic with rebinding `<-` so that is *does* appear on the call stack. – John Coleman Nov 08 '19 at 14:23
  • @JohnColeman Not without a big performance cost. Masking `<-` with a closure is a really bad idea. – Roland Nov 08 '19 at 15:49