Data.table: Try to understand why `mget()` doesn't work here?

Created on 17 May 2016  Â·  10Comments  Â·  Source: Rdatatable/data.table

require(data.table)
dt = data.table(x=c(1,1,2,2,2), y=1, z=2)
vv = 6

dt[, get("vv")] # works fine

# ?!?!?
dt[, mget("vv")]
# Error: value for ‘vv’ not found

Is this a bug? Haven't had time to look into it yet.

bug

Most helpful comment

This is simply because get has inherits = TRUE as default while mget has inherits = FALSE as default. Hence both dt[, mget("vv", inherits = TRUE)] and dt[, mget("vv", envir = as.environment(1))] work.

All 10 comments

Yea something's pretty messed up...

I get SDenv$.SDall to be:

#    x y z x.x x.y x.z
# 1: 1 1 2   1   1   2
# 2: 1 1 2   1   1   2
# 3: 2 1 2   2   1   2
# 4: 2 1 2   2   1   2
# 5: 2 1 2   2   1   2

No way it should be calculating all that!

That said, here is a much simplified version of the error:

f <- function(...){ 
  fenv <- new.env()
  eval(substitute(get("vv")), fenv, parent.frame())}
f()
# [1] 6

g <- function(...){ 
  fenv <- new.env()
  eval(substitute(mget("vv")), fenv, parent.frame())}
g()

Error: value for ‘vv’ not found

This is simply because get has inherits = TRUE as default while mget has inherits = FALSE as default. Hence both dt[, mget("vv", inherits = TRUE)] and dt[, mget("vv", envir = as.environment(1))] work.

That handles that... curious that they have different defaults, any guesses why? Nothing in the dox.

Also, explains why dt[,{vv = 6; mget("vv")}] works (and hence this problem took so long to surface)

@DavidArenburg great! Thanks.

NP, @arunsrinivasan. But why do you think it's a bug? It has nothing to do with data.table and this is a documented/intended behavior in base R...

The idea is that mget() for data.table could be consistent with what one expects within the frame of a data.table, however inconsistent base R is between get() and mget().

So you plan to overload mget within data.table? Or silently add inherits = TRUE when detecting mget in jsub?

Neither seem ideal to me...

inherits=TRUE.

I think it'd be pretty complicated in general to handle this. Tried a simple approach of treating mget like strptime and defining SDenv$mget:

  SDenv$mget = function(...) {
    if ('inherits' %chin% names(list(...))) mget(...) else mget(..., inherits = TRUE)
  }

But this doesn't work as hoped. Unless there's something simple I'm missing I'd say we abandon this

I agree with Michael that it does seems to complicated to handle that. We already know that inherits was responsible for a difference in question. I would advise to use a more general substitution #4304 rather than lookup up symbols in frames via get/mget. Please re-open if you do not agree.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jimhester picture jimhester  Â·  3Comments

andschar picture andschar  Â·  3Comments

alex46015 picture alex46015  Â·  3Comments

DavidArenburg picture DavidArenburg  Â·  3Comments

jangorecki picture jangorecki  Â·  3Comments