Vitaly S.
2010-Aug-15 21:39 UTC
[Rd] parent.frame(1) of a S4 method is not a calling environment.
Dear Developers, I wonder what are the parent.frame rules for methods. For ordinary functions one can call parent.frame() and be sure that it is the environment of a calling function. With S4 aparently it is not the case. Here is what I have discovered by trial and error so far:> setClass("A", contains="vector")[1] "A"> setGeneric("foo", def=function(a, ...){standardGeneric("foo")})[1] "foo"> > setMethod("foo", signature("A"),+ def=function(a, ...){ + cat("--pf1--\n") + ls(parent.frame(1)) + ## cat("--pf2--") + ## ls(parent.frame(2)) + }) [1] "foo"> > tf <- function(){+ b <- 4 + foo(new("A")) #ok + }> > tf() #ok--pf1-- [1] "b" The above works like predicted. Now, a small change. The "b" argument which is not in the signature, but has a role of an additional parameter to the function:> setMethod("foo", signature("A"),+ def=function(a, b, ...){ + cat("--pf1--\n") + print(ls(parent.frame(1))) + cat("--pf2--\n") + print(ls(parent.frame(2))) + }) [1] "foo"> > tf() #oups--pf1-- [1] "a" --pf2-- [1] "b">So, can I be sure that for such functions parent.frame(2) will always work? What are the additional rules? Many thanks, Vitaly.
Martin Morgan
2010-Aug-16 19:12 UTC
[Rd] parent.frame(1) of a S4 method is not a calling environment.
On 08/15/2010 02:39 PM, Vitaly S. wrote:> > Dear Developers, > > I wonder what are the parent.frame rules for methods. For ordinary functions one > can call parent.frame() and be sure that it is the environment of a calling > function. With S4 aparently it is not the case. > > Here is what I have discovered by trial and error so far: > >> setClass("A", contains="vector") > [1] "A" >> setGeneric("foo", def=function(a, ...){standardGeneric("foo")}) > [1] "foo" >> >> setMethod("foo", signature("A"), > + def=function(a, ...){ > + cat("--pf1--\n") > + ls(parent.frame(1)) > + ## cat("--pf2--") > + ## ls(parent.frame(2)) > + }) > [1] "foo" >> >> tf <- function(){ > + b <- 4 > + foo(new("A")) #ok > + } >> >> tf() #ok > --pf1-- > [1] "b" > > The above works like predicted. > Now, a small change. The "b" argument which is not in the signature, but has a > role of an additional parameter to the function: > >> setMethod("foo", signature("A"), > + def=function(a, b, ...){ > + cat("--pf1--\n") > + print(ls(parent.frame(1))) > + cat("--pf2--\n") > + print(ls(parent.frame(2))) > + }) > [1] "foo" >> >> tf() #oups > --pf1-- > [1] "a" > --pf2-- > [1] "b" >> > > So, can I be sure that for such functions parent.frame(2) will always work? > What are the additional rules?callNextMethod() will cause additional problems; the idea that you'll grab things from somewhere other than function arguments doesn't seem like a robust design, even if it's used in some important parts of R. Martin> > Many thanks, > Vitaly. > > ______________________________________________ > R-devel at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel-- Martin Morgan Computational Biology / Fred Hutchinson Cancer Research Center 1100 Fairview Ave. N. PO Box 19024 Seattle, WA 98109 Location: Arnold Building M1 B861 Phone: (206) 667-2793