[Bioc-devel] Lazy evaluation and S4 methods
Ah, you're exactly right -- 'var' is found by lookup in the 'stats' namespace, not the variable I included. (which would be extremely evident if I had printed the output after evaluation...) Thanks, and sorry for the noise! Kevin On Wed, Apr 23, 2014 at 1:29 PM, Michael Lawrence
<lawrence.michael at gene.com> wrote:
It's not really detached from its caller, but the method implementation is just 1-2 layers deeper in the call stack than it would be otherwise. First, there's the generic, then some methods have their bodies embedded in a .local(). I'm honestly not sure why your first vanilla example succeeds. It should not find that 'var' symbol, since you are not passing parent.frame() to eval. Perhaps you accidentally added var to your workspace? On Wed, Apr 23, 2014 at 1:04 PM, Kevin Ushey <kevinushey at gmail.com> wrote:
Thanks Michael -- that looks quite useful. Is my other conjecture true though -- S4 methods are evaluated in an environment detached from the caller, so that regular symbol lookup does not work as it might for regular functions? Or why do I see that behaviour? Kevin On Wed, Apr 23, 2014 at 11:13 AM, Michael Lawrence <lawrence.michael at gene.com> wrote:
The tricky part about your example is that each of the arguments in "..." could be originating from different frames. The S4Vectors:::top_prenv_dots function will give you a list of environments, one for each argument in "...". An example of its use can be found in IRanges::transform.DataTable. I bet top_prenv_dots will be moving to a different package soon, so don't get too attached to anything. Michael On Wed, Apr 23, 2014 at 11:02 AM, Kevin Ushey <kevinushey at gmail.com> wrote:
Hi everyone,
I'm trying to investigate lazy evaluation with S4, and specifically
the environment chain available for lookup when an S4 method is
evaluated.
With 'vanilla' R functions, we can write something like the following:
lazy <- function(...) {
call <- substitute(list(...))
for (i in 2:length(call)) {
eval(call[[i]])
}
}
and evaluation will succeed if this function is called by another
function:
f <- function() {
var <- 10
lazy(x = var)
}
f()
The evaluation of the symbol 'var' is able to find it in the 'f'
environment.
setClass("Lazy", list(data="list"))
setGeneric("lazy", function(x, ...) standardGeneric("lazy"))
setMethod("lazy", list(x="Lazy"), function(x, ...) {
call <- substitute(list(...))
for (i in 2:length(call)) {
eval( call[[i]] )
}
})
f <- function() {
var <- new("Lazy", data=list(1))
y <- 1
cat("\n")
lazy(var, a=y)
}
f()
gives ' Error in eval(expr, envir, enclos) : object 'y' not found '.
It seems like the S4 method is evaluated in an environment detached
from the scope of the caller (which is probably outlined in ?Methods,
but I am having trouble parsing everything in there).
My main question is -- is there a nice way to work around this, in a
way that is transparent to the user of a function?
Further motivation available in the GitHub issue for flowCore here:
https://github.com/RGLab/ncdfFlow/issues/31
Thanks,
Kevin
_______________________________________________ Bioc-devel at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/bioc-devel