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
> >
> >
>

        [[alternative HTML version deleted]]

_______________________________________________
Bioc-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/bioc-devel

Reply via email to