[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