R data.table: evaluating address of an object in parent frame

Viewed 77

I'm trying to evaluate an expression containing an address of an object at a parent.frame scope, and am getting weird results:

test2 <- function(d) {
  address.current <- address(d)                          # "0x5595b73aedf8"
  address.at.caller <- eval(parse(text="address(df)"))   # "0x5595b73aedf8"
  address.at.caller2 <- do.call(address, args=list("df"), envir=parent.frame())   # problem: "0x5595b6d89de8"
}

test1 <- function(df) {
  test2(df)
}

df <- data.frame(a=1:2)
test1(df)

Moreover, if you stop at a breakpoint inside test2 and re-evaluate the expression for address.at.caller2 you'd get non-repeating results:

Browse[2]> do.call(address, args=list("df"), envir=parent.frame())
[1] "0x5595b8c37d78"
Browse[2]> do.call(address, args=list("df"), envir=parent.frame())
[1] "0x5595b8cc74a8"
Browse[2]> do.call(address, args=list("df"), envir=parent.frame())
[1] "0x5595b8cd1348"

This seems to indicate that the result is an address of some temporary object. (Evaluate repeatedly address(2) for a different example).

Is something wrong with the expression do.call(address, args=list("df"), envir=parent.frame())?

Is there a different explanation for this behaviour?

2 Answers

Its not really clear what you are trying to do by using do.call. When you use it like you did, you gave it a variable ( a string) and you asked it for the address. the thing is that R automatically creates copies when you enter variables into functions. So when you gave args = list("df) what R did was create a copy of the string "df" within the do.call frame, and then it gave you the local address before closing the call. You should pass the variable you want to evaluate into the function, or alternatively have it sit on the global scope.

Interesting question.
You don't have to pass input variable really, or operate on the global scope. You can use a more robust alternative to do.call, the eval(as.call(.)).

test2 <- function(d) {
  address.current <- address(d)
  print(address.current)
  address.at.caller <- eval(parse(text="address(df)"))
  print(address.at.caller)
  address.at.caller2 <- do.call(address, args=list("df"), envir=parent.frame())
  print(address.at.caller2)
  address.at.caller3 = eval.parent(as.call(list(quote(address), as.name("df"))))
  print(address.at.caller3)
}

test1 <- function(df) {
  test2(df)
}

df <- data.frame(a=1:2)
test1(df)
[1] "0x560d46e33cc0"
[1] "0x560d46e33cc0"
[1] "0x560d46e4a5f8"
[1] "0x560d46e33cc0"
Related