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.mich...@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 <kevinus...@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.mich...@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 <kevinus...@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@r-project.org mailing list >> >> https://stat.ethz.ch/mailman/listinfo/bioc-devel >> > >> > > > _______________________________________________ Bioc-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/bioc-devel