[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:

    contains = "numeric",
    validity = function(object)
        stopifnot(object[1] == object[2])

setGeneric("MyClassA", function(x) standardGeneric("MyClassA"))

    signature(x = "numeric"),
        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"))

        ca = "MyClassAOrNULL"
    prototype(ca = NULL)

setGeneric("MyClassB", function(x) standardGeneric("MyClassB"))

    signature(x = "MyClassA"),
        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) 

 [1] LC_CTYPE=en_GB       LC_NUMERIC=C         LC_TIME=en_GB

attached base packages:
[1] splines   stats     graphics  utils     datasets  grDevices methods

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