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):
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/webloghttp://www.fss.uu.nl/soc/bojanowskihttp://www.ifispan.waw.pl/socnierowno
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):
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?
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
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.
Thanks a lot, I was not aware of that. Given that 'pixmap' package does not
have a namespace I was somehow convinced that all the classes and methods
provided by this package will be visible for other packages. In fact, I was
also convinced that the '::' operator applies only to packages with namespaces.
Which is not the case and the help page for :: is clear about that.
the only solution is
pixmap::plot(x=x at img, ...)