[Rd] Bug: broken exception handling in S4 methods
Sklyar, Oleg (London)
osklyar at ahl.com
Wed Jul 21 11:36:59 CEST 2010
Hi all:
we have noticed for quite a while that certain errors cannot be handled
by R try, tryCatch etc blocks, but it was fairly difficult to understand
what were the conditions for this incorrect behaviour. Finally I stabbed
across a very understandable case, which is outlined in the (runnable)
example below.
The main message is: wrapping an S4 method call in a try block will not
help if an error occurs in evaluating an argument to such a call; this
works just fine for function calls (as opposed to S4 methods)
The particular example is a result of trying to write a unit test for a
constructor of a class object which should fail under certain
conditions. This failure obviously need to be caught for the unit test
to proceed. However, it is a general problem with handling some
exceptions in R.
# Consider a simple class MyClassA, which is derived from numeric and
for which
# we define a constructor (in form of a method). On its own this class
works nicely
# and so does exception handling of it:
setClass("MyClassA",
contains = "numeric",
validity = function(object)
{
stopifnot(object[1] == object[2])
TRUE
}
)
setGeneric("MyClassA", function(x) standardGeneric("MyClassA"))
setMethod("MyClassA",
signature(x = "numeric"),
function(x)
{
new("MyClassA", x)
}
)
## OK
er = try({ MyClassA(c(1,2)) })
## OK (error in constructor)
er = try({ MyClassA(c(1,2)) })
## OK (error evaluating argument to a function)
er = try({ sin(MyClassA(c(1,2))) })
# Now consider we define MyClassB that has MyClassA in a slot
# and we define a constructor that takes such objects:
setClassUnion("MyClassAOrNULL", c("MyClassA", "NULL"))
setClass("MyClassB",
representation(
ca = "MyClassAOrNULL"
),
prototype(ca = NULL)
)
setGeneric("MyClassB", function(x) standardGeneric("MyClassB"))
setMethod("MyClassB",
signature(x = "MyClassA"),
function(x)
{
new("MyClassB", ca = x)
}
)
## OK
b = MyClassB(MyClassA(c(1,1)))
## FAILS (error evaluating argument to a method)
er = try({ MyClassB(MyClassA(c(1,2))) })
# As you see the last error cannot be handled
# Moreover. If we define a function and a method as function(x) x then
# the function can be handled by try, yet the method cannot:
f = function(x) x
setGeneric("g", function(x) standardGeneric("g"))
setMethod("g", "MyClassA", function(x) x)
## OK (error evaluating argument to a function)
er = try({ f(MyClassA(c(1,2))) })
## FAILS (error evaluating argument to a method)
er = try({ g(MyClassA(c(1,2))) })
> sessionInfo()
R version 2.11.0 Patched (2010-05-05 r51914)
x86_64-unknown-linux-gnu
locale:
[1] LC_CTYPE=en_GB LC_NUMERIC=C LC_TIME=en_GB
LC_COLLATE=en_GB
[5] LC_MONETARY=C LC_MESSAGES=en_GB LC_PAPER=en_GB
LC_NAME=C
[9] LC_ADDRESS=C LC_TELEPHONE=C LC_MEASUREMENT=en_GB
LC_IDENTIFICATION=C
attached base packages:
[1] splines stats graphics utils datasets grDevices methods
base
Dr Oleg Sklyar
Research Technologist
AHL / Man Investments Ltd
+44 (0)20 7144 3803
osklyar at ahl.com
**********************************************************************
Please consider the environment before printing this email or its attachments.
The contents of this email are for the named addressees ...{{dropped:19}}
More information about the R-devel
mailing list