MichaĆ Bojanowski
2009-May-18 13:31 UTC
[Rd] S4 method dispatch and namespaces: why is default method selected
Hi, I ran into the following peculiarity involving S4 method dispatch and namespaces. I develop a package which have a namespace and which depends on 'pixmap' package, which itself does not have a namespace. Now, in my package I have a class which has a slot for objects from class "pixmap" and I want to have a "plot" method for this new class. Not to clutter the point with my original code here is a stylized example: # library(pixmap) # so that the class pixmap is available # class setClass("myclass", representation(img="pixmap", title="character", other="numeric")) # method to plot setMethod("plot", signature(x="myclass", y="missing"), function(x, main=x at title, ...) { # plot using the method from pixmap package plot(x=x at img, ...) title(main=main) points(seq(along=x at other), other) } ) Now, if you try to do this: library(pixmap) f <- system.file(file.path("pictures", "logo.ppm"), package="pixmap") o <- new("myclass", img=read.pnm(f), title="some title", other=Inf) o # now this works as the plot method for signature x="pixmap" y="ANY" is # dispatched correctly plot(o) However, when I put all these in a package with Depends field in DESCRIPTION having: methods, pixmap, and with the following namespace: importFrom("graphics", "plot") exportClasses("myclass") exportMethods("plot") things stop working (this is from package test):> f <- system.file(file.path("pictures", "logo.ppm"), package="pixmap") > o <- new("myclass", a=read.pnm(f), title="tytul") > plot(o)Error in as.double(y) : cannot coerce type 'S4' to vector of type 'double' Calls: plot ... plot -> .local -> plot -> plot.default -> xy.coords Execution halted So apparently calling 'plot' dispatches the default method instead of using the one from package 'pixmap'. Why? As far as I understand the documentation and section 10.6 of "Software for Data Analysis" the default method should never be selected as far as there are other candidates. And there seems to be other candidates, and they seem to be properly selected if checked using 'selectMethod' (this is from results from package tests):> showMethods("plot")Function: plot (package graphics) x="ANY", y="ANY" x="myclass", y="missing" x="pixmap", y="ANY"> selectMethod("plot", signature(x="pixmap", y="missing"))Method Definition: function (x, y, ...) { .local <- function (x, y, xlab = "", ylab = "", axes = FALSE, asp = 1, ...) { x = as(x, "pixmapIndexed") X <- seq(x at bbox[1], x at bbox[3], by = x at cellres[1]) Y <- seq(x at bbox[2], x at bbox[4], by = x at cellres[2]) image(x = X, y = Y, z = t(x at index[nrow(x at index):1, , drop = FALSE]), col = x at col, xlab = xlab, ylab = ylab, axes = axes, asp = asp, ...) } .local(x, y, ...) } <environment: 0x01844e60> Signatures: x y target "pixmap" "missing" defined "pixmap" "ANY"> sessionInfo()R version 2.9.0 (2009-04-17) i386-pc-mingw32 locale: LC_COLLATE=Polish_Poland.1250;LC_CTYPE=Polish_Poland.1250;LC_MONETARY=Polish_Poland.1250;LC_NUMERIC=C;LC_TIME=Polish_Poland.1250 attached base packages: [1] stats graphics grDevices utils datasets methods base other attached packages: [1] pixmap_0.4-9 loaded via a namespace (and not attached): [1] tools_2.9.0 Thanks in advance! Best, Micha? _________________________ Michal Bojanowski http://bojan.3e.pl/weblog http://www.fss.uu.nl/soc/bojanowski http://www.ifispan.waw.pl/socnierowno
Martin Morgan
2009-May-19 03:59 UTC
[Rd] S4 method dispatch and namespaces: why is default method selected
Hi Micha? -- Micha? Bojanowski <michal2992 at gmail.com> writes:> Hi, > > I ran into the following peculiarity involving S4 method dispatch and > namespaces. > > I develop a package which have a namespace and which depends on 'pixmap' > package, which itself does not have a namespace. > > Now, in my package I have a class which has a slot for objects from > class "pixmap" and I > want to have a "plot" method for this new class. Not to clutter the point with > my original code here is a stylized example: > > > # library(pixmap) # so that the class pixmap is available > > # class > setClass("myclass", representation(img="pixmap", title="character", > other="numeric")) > > # method to plot > setMethod("plot", signature(x="myclass", y="missing"), > function(x, main=x at title, ...) > { > # plot using the method from pixmap package > plot(x=x at img, ...) > title(main=main) > points(seq(along=x at other), other) > } ) > > > Now, if you try to do this: > > library(pixmap) > f <- system.file(file.path("pictures", "logo.ppm"), package="pixmap") > o <- new("myclass", img=read.pnm(f), title="some title", other=Inf) > o > > # now this works as the plot method for signature x="pixmap" y="ANY" is > # dispatched correctly > plot(o) > > > > However, when I put all these in a package with Depends field in > DESCRIPTION having: methods, pixmap, and with the following namespace: > > > importFrom("graphics", "plot") > exportClasses("myclass") > exportMethods("plot") > > > things stop working (this is from package test): > > >> f <- system.file(file.path("pictures", "logo.ppm"), package="pixmap") >> o <- new("myclass", a=read.pnm(f), title="tytul") >> plot(o) > Error in as.double(y) : > cannot coerce type 'S4' to vector of type 'double' > Calls: plot ... plot -> .local -> plot -> plot.default -> xy.coords > Execution halted > > > > So apparently calling 'plot' dispatches the default method instead of using the > one from package 'pixmap'. Why?Not speaking authoritatively, but plot,myclass,missing-method is defined in your name space, and so has access only to symbols defined or imported into the name space. The plot,pixmap,ANY-method is not in your name space (even though it's on the search path), and so is not found. Clever of the methods package to keep track of this. I think the only solution is pixmap::plot(x=x at img, ...) Martin> As far as I understand the documentation and section 10.6 of "Software for Data > Analysis" the default method should never be selected as far as there are other > candidates. And there seems to be other candidates, and they seem to be properly > selected if checked using 'selectMethod' (this is from results from > package tests): > > > > >> showMethods("plot") > Function: plot (package graphics) > x="ANY", y="ANY" > x="myclass", y="missing" > x="pixmap", y="ANY" > > >> selectMethod("plot", signature(x="pixmap", y="missing")) > Method Definition: > > function (x, y, ...) > { > .local <- function (x, y, xlab = "", ylab = "", axes = FALSE, > asp = 1, ...) > { > x = as(x, "pixmapIndexed") > X <- seq(x at bbox[1], x at bbox[3], by = x at cellres[1]) > Y <- seq(x at bbox[2], x at bbox[4], by = x at cellres[2]) > image(x = X, y = Y, z = t(x at index[nrow(x at index):1, , > drop = FALSE]), col = x at col, xlab = xlab, ylab = ylab, > axes = axes, asp = asp, ...) > } > .local(x, y, ...) > } > <environment: 0x01844e60> > > Signatures: > x y > target "pixmap" "missing" > defined "pixmap" "ANY" > > > > > >> sessionInfo() > R version 2.9.0 (2009-04-17) > i386-pc-mingw32 > > locale: > LC_COLLATE=Polish_Poland.1250;LC_CTYPE=Polish_Poland.1250;LC_MONETARY=Polish_Poland.1250;LC_NUMERIC=C;LC_TIME=Polish_Poland.1250 > > attached base packages: > [1] stats graphics grDevices utils datasets methods base > > other attached packages: > [1] pixmap_0.4-9 > > loaded via a namespace (and not attached): > [1] tools_2.9.0 > > > > > Thanks in advance! > > Best, > Micha? > > > > _________________________ > Michal Bojanowski > http://bojan.3e.pl/weblog > http://www.fss.uu.nl/soc/bojanowski > http://www.ifispan.waw.pl/socnierowno > > ______________________________________________ > 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