Can someone explain what the problem is when I use the
generating function? And how to get debug() to stop in
the Superclass initialize method?
---- source -----
setClass("Superclass",
representation(id = "character"),
contains = "VIRTUAL")
setMethod("initialize",
signature(.Object = "Superclass"),
function(.Object, id = "") {
cat("initialize (Superclass)", "\n")
if (length(id) > 0) {
cat("\tid =", id, "\n")
.Object at id <- id
}
.Object
})
setClass("Subclass",
contains = "Superclass")
setMethod("initialize",
signature(.Object = "Subclass"),
function(.Object, ...) {
cat("initialize (Subclass)", "\n")
cat("\t... =");str(list(...));cat("\n")
callNextMethod(.Object, ...)
})
Subclass <- function(id = "") {
new("Subclass", id = id)
}
cat("*** Create class using new() ***\n")
str(new("Subclass", id = "test1"))
cat("*** Create class using generating function ***\n")
str(Subclass(id = "test2"))
---- output -----
*** Create class using new() ***
initialize (Subclass)
... =List of 1
$ id: chr "test1"
initialize (Superclass)
id = test1
Formal class 'Subclass' [package ".GlobalEnv"] with 1 slots
..@ id: chr "test1"
*** Create class using generating function ***
initialize (Subclass)
... =List of 1
$ id: chr "test2"
initialize (Superclass)
Error in .local(.Object, ...) : Object "id" not found
Thanks
----------------------------------------------------------
SIGSIG -- signature too long (core dumped)
S4 generating function
4 messages · Paul Roebuck, John Chambers
First, anyone planning to debug methods should consider the general form
of the trace() function with signature= to say what method to trace, and
some suitable interactive function such as "browser" or "recover" to
examine the computations. See ?trace
In this example, something like:
trace("initialize", sig="Superclass", browser)
Now, the specific example. There are 3 special features used:
1. Nonstandard arguments for the initialize method (its official
arguments are (.Object, ...))
2. callNextMethod
3. within callNextMethod, providing explicit arguments. The simple case
is callNextMethod(), which passes on the arguments to the current method.
Turns out that it's the third step that finds a bug in the heuristics
used by callNextMethod to construct the actual call.
In your example, you don't need the explicit arguments since they just
replicate the formal arguments to initialize(). If you omit them, the
computation is simpler & works.
The bug can probably be fixed, but until 2.2 comes out at least, you
need to stick to the simpler callNextMethod().
Removing the extraneous cat() and str() calls, the revised example is:
------------
R> setClass("Superclass", representation(id = "character"),
contains = "VIRTUAL")
[1] "Superclass"
R> setMethod("initialize", signature(.Object = "Superclass"),
function(.Object, id = "") {
if (length(id) > 0) {
.Object at id <- i .... [TRUNCATED]
[1] "initialize"
R> setClass("Subclass", contains = "Superclass")
[1] "Subclass"
R> setMethod("initialize", signature(.Object = "Subclass"),
function(.Object, ...) {
callNextMethod()
})
[1] "initialize"
R> Subclass <- function(id = "") {
new("Subclass", id = id)
}
R> new("Subclass", id = "test1")
An object of class ?Subclass?
Slot "id":
[1] "test1"
R> Subclass(id = "test2")
An object of class ?Subclass?
Slot "id":
[1] "test2"
-----------------------
Paul Roebuck wrote:
Can someone explain what the problem is when I use the
generating function? And how to get debug() to stop in
the Superclass initialize method?
---- source -----
setClass("Superclass",
representation(id = "character"),
contains = "VIRTUAL")
setMethod("initialize",
signature(.Object = "Superclass"),
function(.Object, id = "") {
cat("initialize (Superclass)", "\n")
if (length(id) > 0) {
cat("\tid =", id, "\n")
.Object at id <- id
}
.Object
})
setClass("Subclass",
contains = "Superclass")
setMethod("initialize",
signature(.Object = "Subclass"),
function(.Object, ...) {
cat("initialize (Subclass)", "\n")
cat("\t... =");str(list(...));cat("\n")
callNextMethod(.Object, ...)
})
Subclass <- function(id = "") {
new("Subclass", id = id)
}
cat("*** Create class using new() ***\n")
str(new("Subclass", id = "test1"))
cat("*** Create class using generating function ***\n")
str(Subclass(id = "test2"))
---- output -----
*** Create class using new() ***
initialize (Subclass)
... =List of 1
$ id: chr "test1"
initialize (Superclass)
id = test1
Formal class 'Subclass' [package ".GlobalEnv"] with 1 slots
..@ id: chr "test1"
*** Create class using generating function ***
initialize (Subclass)
... =List of 1
$ id: chr "test2"
initialize (Superclass)
Error in .local(.Object, ...) : Object "id" not found
Thanks
----------------------------------------------------------
SIGSIG -- signature too long (core dumped)
______________________________________________ R-devel at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
On Fri, 5 Aug 2005, John Chambers wrote:
Paul Roebuck wrote:
Can someone explain what the problem is when I use the generating function? And how to get debug() to stop in the Superclass initialize method? [SNIP code & output]
Now, the specific example. There are 3 special features used: 1. Nonstandard arguments for the initialize method (its official arguments are (.Object, ...)) 2. callNextMethod 3. within callNextMethod, providing explicit arguments. The simple case is callNextMethod(), which passes on the arguments to the current method. Turns out that it's the third step that finds a bug in the heuristics used by callNextMethod to construct the actual call. In your example, you don't need the explicit arguments since they just replicate the formal arguments to initialize(). If you omit them, the computation is simpler & works. The bug can probably be fixed, but until 2.2 comes out at least, you need to stick to the simpler callNextMethod(). [SNIP modified code]
Thank you for your help. Unfortunately, this is a case where
posting the simplest code necessary to display the bug works
against the poster. Actual code uses external pointers but
this revision shows more of the general concept.
If I understand your description correctly, the problem is
passing both named and unnamed arguments to callNextMethod().
Can I [easily] do either of these things to avoid the bug?
1) somehow add an argument to 'dots' and invoke callNextMethod()
without arguments?
2) parse 'dots' and invoke callNextMethod() with a completely
named argument list?
------ revised source -------
setClass("Superclass",
representation(.values = "integer",
id = "character"),
contains = "VIRTUAL")
setMethod("initialize",
signature(.Object = "Superclass"),
function(.Object, .values = NULL, id = "") {
cat("initialize (Superclass)", "\n")
if (!is.null(.values)) {
cat("\t.values =", .values, "\n")
.Object at .values <- .values
}
if (length(id) > 0) {
cat("\tid =", id, "\n")
.Object at id <- id
}
.Object
})
setClass("Subclass",
contains = "Superclass")
setMethod("initialize",
signature(.Object = "Subclass"),
function(.Object, count = 1, ...) {
cat("initialize (Subclass)", "\n")
dots <- list(...)
cat("\t... =");str(dots);cat("\n")
.values = integer(count)
callNextMethod(.Object, .values = .values, ...)
})
Subclass <- function(count, id = "") {
new("Subclass", count, id = id)
}
cat("*** Create class using new() ***\n")
str(new("Subclass", id = "test0"))
str(new("Subclass", count = 3, id = "test1"))
cat("*** Create class using generating function ***\n")
#trace("initialize", signature = "Subclass", browser)
str(Subclass(count = 3, id = "test2"))
----------------------------------------------------------
SIGSIG -- signature too long (core dumped)
Re: > If I understand your description correctly, the problem is > passing both named and unnamed arguments to callNextMethod(). No, as I said the distinction is a potential bug in callNextMethod _whenever_ it gets explicit arguments. (At the moment, it seems to be a bug in substitute() or else a different interpretation of that function from the one in the Blue Book. But I've only looked a little.) So to work around it you have to be able to do callNextMethod() with no arguments. Just at a guess, you may be able to do that if you avoid redefining the formal arguments for the initialize() method. Leave them as .Object, ... and extract the id= component. dotArgs <- list(...) id <- dotArgs$id Or, wait for a fix. There should at least be one in r-devel sometime fairly soon.
Paul Roebuck wrote:
On Fri, 5 Aug 2005, John Chambers wrote:
Paul Roebuck wrote:
Can someone explain what the problem is when I use the generating function? And how to get debug() to stop in the Superclass initialize method? [SNIP code & output]
Now, the specific example. There are 3 special features used: 1. Nonstandard arguments for the initialize method (its official arguments are (.Object, ...)) 2. callNextMethod 3. within callNextMethod, providing explicit arguments. The simple case is callNextMethod(), which passes on the arguments to the current method. Turns out that it's the third step that finds a bug in the heuristics used by callNextMethod to construct the actual call. In your example, you don't need the explicit arguments since they just replicate the formal arguments to initialize(). If you omit them, the computation is simpler & works. The bug can probably be fixed, but until 2.2 comes out at least, you need to stick to the simpler callNextMethod(). [SNIP modified code]
Thank you for your help. Unfortunately, this is a case where
posting the simplest code necessary to display the bug works
against the poster. Actual code uses external pointers but
this revision shows more of the general concept.
If I understand your description correctly, the problem is
passing both named and unnamed arguments to callNextMethod().
Can I [easily] do either of these things to avoid the bug?
1) somehow add an argument to 'dots' and invoke callNextMethod()
without arguments?
2) parse 'dots' and invoke callNextMethod() with a completely
named argument list?
------ revised source -------
setClass("Superclass",
representation(.values = "integer",
id = "character"),
contains = "VIRTUAL")
setMethod("initialize",
signature(.Object = "Superclass"),
function(.Object, .values = NULL, id = "") {
cat("initialize (Superclass)", "\n")
if (!is.null(.values)) {
cat("\t.values =", .values, "\n")
.Object at .values <- .values
}
if (length(id) > 0) {
cat("\tid =", id, "\n")
.Object at id <- id
}
.Object
})
setClass("Subclass",
contains = "Superclass")
setMethod("initialize",
signature(.Object = "Subclass"),
function(.Object, count = 1, ...) {
cat("initialize (Subclass)", "\n")
dots <- list(...)
cat("\t... =");str(dots);cat("\n")
.values = integer(count)
callNextMethod(.Object, .values = .values, ...)
})
Subclass <- function(count, id = "") {
new("Subclass", count, id = id)
}
cat("*** Create class using new() ***\n")
str(new("Subclass", id = "test0"))
str(new("Subclass", count = 3, id = "test1"))
cat("*** Create class using generating function ***\n")
#trace("initialize", signature = "Subclass", browser)
str(Subclass(count = 3, id = "test2"))
----------------------------------------------------------
SIGSIG -- signature too long (core dumped)