[Bioc-devel] Lazy evaluation and S4 methods
Kevin Ushey
kevinushey at gmail.com
Wed Apr 23 22:32:23 CEST 2014
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
>> >
>> >
>
>
More information about the Bioc-devel
mailing list