Recursion error after upgrade to R_2.11.1 [Sec=Unclassified] [Sec=Unclassified]
On 10/06/2010 06:12 PM, Troy Robertson wrote:
Hi all, After no replies to my previous message I thought I might show some code to demonstrate the change and again seek any
explanation for the
error now thrown by my code after upgrading from 2.10.1 to 2.11.1.
Thanks
Troy
--------------------------------------------------------
setClass("PortableObject",
representation(test1 = "character"),
prototype( test1 = ""),
contains = ".environment"
)
setMethod("initialize", "PortableObject",
function(.Object, ..., .xData=new.env(parent=emptyenv())) {
.Object <- callNextMethod(.Object, ...,
.xData=.xData)
.Object at test1 <- "Foo"
# Following line works under 2.10.1 but now throws
# Error: evaluation nested too deeply:
infinite recursion / options(expressions=)?
#####.Object[["test2"]] <- "Bar"
# The following does what I want though
.Object$test3 <- "Baa"
return(.Object)
}
)
e <- new("PortableObject")
The explicit example does help -- it's clear what bug you are encountering. Here's the code in R-2.10
selectMethod("[[<-", ".environment")
Method Definition:
function (x, i, j, ..., value)
{
call <- sys.call()
call[[2]] <- x at .Data
eval.parent(call)
x
}
and 2.11.1
selectMethod("[[<-", ".environment")
Method Definition:
function (x, i, j, ..., value)
{
.local <- function (x, i, j, ..., exact = TRUE, value)
{
call <- sys.call()
call[[2]] <- x at .Data
eval.parent(call)
x
}
.local(x, i, j, ..., value = value)
}
Apparently the 'exact' argument has been added, and because
the method signature differs from the generic, a .local
function is created. That 'sys.call()' originally returned
the environment in which the generic was called, but now it
returns the environment in which .local is defined. And so
eval() keeps evaluating .local(). This I think is a bug.
Yes, afer the email from William Dunlop, I found this difference in the methods between 2.10.1 and 2.11.1
I had a play and by adding my own method to overload "[[<-" for my PortableObject was able to reinstate the original functionality without the recursive error.
setMethod("[[<-", "PortableObject",
function (x, i, j, ..., value)
{
call <- sys.call()
call[[2]] <- x at .Data
eval.parent(call)
x
}
)
For what it's worth, if I were interested in minimizing copying I would set up initialize so that it ended with callNextMethod(<...>), on the hopes that the method eventually called would take care not to make too many copies on slot assignment. Martin
Hmmm, not sure what you mean here? My code passes objects such as these as parameters to other S4 classes which alter their data. If the .xData slot is used then I have no need to return the object. No copy-on-change is performed but data held by the PortableObject is modified. This speeds up my execution time by a LARGE amount. I could very well have things all arse-about, having come from a Java OO background, but this is the only way I have been able to create a pass-by-reference paradigm using S4 classes. Any suggestions for alternative solutions would be greatfully received. Troy
alterEGo <- function(o = "EPOCObject") {
o at test1 <- "Boo"
# Following line works under 2.10.1 but now throws
# Error: evaluation nested too deeply: infinite
recursion / options(expressions=)?
####o[["test2"]] <- "Who"
# The following does what I want though
o$test3 <- "Hoo"
# NOTE: No return
}
alterEGo(e)
e at test1
e$test2
e[["test3"]]
e at .xData[["test3"]]
___________________________________________________________________________
Australian Antarctic Division - Commonwealth of Australia
IMPORTANT: This transmission is intended for the addressee only. If you are not the
intended recipient, you are notified that use or dissemination of this communication is
strictly prohibited by Commonwealth law. If you have received this transmission in error,
please notify the sender immediately by e-mail or by telephoning +61 3 6232 3209 and
DELETE the message.
Visit our web site at http://www.antarctica.gov.au/
___________________________________________________________________________