Hello, I wonder if this will make it through the spam filters given the subject line. I'm seeing the following when trying to call a dollar method inside of a dollar method. setClass("Foo", representation(d="list")) [1] "Foo" f <- new("Foo", d=list(bob=1, alice=2)) ## We can call dollar at this level and it works as expected `$`(f, "bo") [1] 1 `$`(f, "al") [1] 2 ## So set a method on Foo that does this setMethod("$", "Foo", function(x, name) `$`(x at d, name)) [1] "$" ## But it doesn't work. Why? f$bo NULL f$al NULL ## Here is a hackish workaround. setMethod("$", "Foo", function(x, name) eval(substitute(x at d$FOO, list(FOO=name)))) [1] "$" f$bo [1] 1 f$al [1] 2 Other suggestions for workarounds? Is this a bug? + seth -- Seth Falcon | Computational Biology | Fred Hutchinson Cancer Research Center http://bioconductor.org
Seth Falcon wrote:> Hello, > > I wonder if this will make it through the spam filters given the > subject line. > > I'm seeing the following when trying to call a dollar method inside of > a dollar method. > > > setClass("Foo", representation(d="list")) > [1] "Foo" > > f <- new("Foo", d=list(bob=1, alice=2)) > > ## We can call dollar at this level and it works as expected > > `$`(f, "bo") > [1] 1 > > `$`(f, "al") > [1] 2 >`$`(f at d, "bo"), surely.> ## So set a method on Foo that does this > > setMethod("$", "Foo", function(x, name) `$`(x at d, name)) > [1] "$" > > ## But it doesn't work. Why? > >This has nothing to do with methods, it's $'s nonstandard evaluation rules that are doing you in. This doesn't work either > x <- "al" > `$`(f at d, x) NULL and the reason is that `$`(a,b) is _exactly_ equivalent to a$b insofar as auto-quoting the second argument is concerned> f$bo > NULL > > f$al > NULL > >...so both of these look for f at d$name which isn't there.> ## Here is a hackish workaround. > > setMethod("$", "Foo", function(x, name) > eval(substitute(x at d$FOO, list(FOO=name)))) > [1] "$" > > f$bo > [1] 1 > > f$al > [1] 2 > > Other suggestions for workarounds? Is this a bug? >Not a bug. Another workaround is to use "[[", but beware that Robert has evil intentions with respect to that and partial matching...
In x$name, 'name' is supposed to be a symbol, unevaluated, or a literal character string (but not a character vector).> f <- list(bob=1, alice=2) > `$`(f, "bob")[1] 1> nm <- "bob" > `$`(f, nm)NULL illustrates your misunderstanding. Note that the S4 generic for $ in fact is "$" = function(x, name) { name <- as.character(substitute(name)) standardGeneric("$") } so within S4 dispatch you will have a character vector for 'name'. You need substitute() to get back to a literal character string. I think the latter should be documented somewhere, but like many details of S4, it is not AFAIK. On Mon, 7 May 2007, Seth Falcon wrote:> Hello, > > I wonder if this will make it through the spam filters given the > subject line. > > I'm seeing the following when trying to call a dollar method inside of > a dollar method. > > > setClass("Foo", representation(d="list")) > [1] "Foo" > > f <- new("Foo", d=list(bob=1, alice=2)) > > ## We can call dollar at this level and it works as expected > > `$`(f, "bo") > [1] 1 > > `$`(f, "al") > [1] 2 > > ## So set a method on Foo that does this > > setMethod("$", "Foo", function(x, name) `$`(x at d, name)) > [1] "$" > > ## But it doesn't work. Why? > > f$bo > NULL > > f$al > NULL > > ## Here is a hackish workaround. > > setMethod("$", "Foo", function(x, name) > eval(substitute(x at d$FOO, list(FOO=name)))) > [1] "$" > > f$bo > [1] 1 > > f$al > [1] 2 > > Other suggestions for workarounds? Is this a bug? > > + seth > >-- Brian D. Ripley, ripley at stats.ox.ac.uk Professor of Applied Statistics, http://www.stats.ox.ac.uk/~ripley/ University of Oxford, Tel: +44 1865 272861 (self) 1 South Parks Road, +44 1865 272866 (PA) Oxford OX1 3TG, UK Fax: +44 1865 272595