From scott.chasalow at bms.com  Fri Mar 18 18:21:30 2005
From: scott.chasalow at bms.com (scott.chasalow@bms.com)
Date: Fri Mar 18 18:21:38 2005
Subject: [Rd] 2 possible bugs in function validObject (PR#7735)
Message-ID: <20050318172130.567DBC6F9@slim.kubism.ku.dk>

Hi,

> R.version.string
[1] "R version 2.0.1, 2004-11-15"

I have found two possible bugs in function validObject.  Details below.

Cheers,
Scott

==================================
Scott D. Chasalow
Principal Statistician
Statistical Genetics and Biomarkers
Bristol-Myers Squibb Company
Email: scott.chasalow <AT> bms.com
==================================

------ BEGIN R commands and output ------
setClass("track",
      representation(x = "numeric", y = "numeric"))

validTrackObject <- function(x){
      if(length(x@x) == length(x@y)) TRUE
      else paste("Oooo that's bad", LETTERS[1:4])
}

## assign the function as the validity method for the class
setValidity("track", validTrackObject)

## Now define class "field", to include a "track" slot:
setClass("field",
      representation(t = "track", z = "character"))
setValidity("field", function(object) if (length(object@z) > 0)
      TRUE else "z is way short.")

## A good track: OK
t1 <- new("track", x = 1:10, y = sort(rnorm(10)))

## A good field: OK
f1 <- new("field", t = t1, z = letters[1:10])

## A bad field: OK
f1 <- new("field", t = t1)
Error in validObject(.Object) : Invalid "field" object: z is way short.

## Make t1 a bad track:  minor problem with error msg formatting?
t1@x <- 1:20
validObject(t1)
Error in validObject(t1) : Invalid "track" object: 1: Oooo that's bad A
Invalid "track" object: 2: Oooo that's bad B
Invalid "track" object: 3: Oooo that's bad C
Invalid "track" object: 4: Oooo that's bad D

## A bad field, because it contains a bad track (an invalid track
## object): fools validObject.  I expected that I would fail to create
## f1 here, or at least that validObject(f1) would report the problem
## with t1 in slot t.
f1 <- new("field", t = t1, z = letters[1:10])
validObject(f1)
[1] TRUE

validObject(f1@t)
Error in validObject(f1@t) : Invalid "track" object: 1: Oooo that's bad A
Invalid "track" object: 2: Oooo that's bad B
Invalid "track" object: 3: Oooo that's bad C
Invalid "track" object: 4: Oooo that's bad D


## A bad field, because I try to put a non-track in the track slot: OK
f1 <- new("field", t = 1:3, z = letters[1:10])
Error in validObject(.Object) : Invalid "field" object: Invalid object
for slot "t" in class "field": got class "integer", should be or extend
class "track"
------  END R commands and output ------


So, we see that validity of slot t is not tested, in the sense of
calling validObject on the slot.  The documentation for validObject
suggests (to me at least) that validObject should be called on the
slot.  Instead, validObject seems to test only that the slot has the
right class.  I'm not sure precisely what the author intended
validObject to do, but this seems to me either a bug in the code, or
else somewhat misleading documentation.

Concerning the error msg formatting, I suspect it possibly is not as
the author intended?  The code in validObject to create this error msg
is:

stop(paste("Invalid \"", Class, "\" object: ",
paste(paste(1:length(errors),
      errors, sep = ": ")), sep = "", collapse = "\n"))

As far as I can see, the second call to paste does nothing here.
Perhaps this is what was intended?:

stop(paste("Invalid \"", Class, "\" object: ",
paste(paste(1:length(errors),
      errors, sep = ": "), collapse = "\n"), sep = ""))

This would give:

Error in validObj(t1) : Invalid "track" object: 1: Oooo that's bad A
2: Oooo that's bad B
3: Oooo that's bad C
4: Oooo that's bad D

Personally, I like this even better:

stop(paste("Invalid \"", Class, "\" object:\n",
paste(paste(1:length(errors),
      errors, sep = ": "), collapse = "\n"), sep = ""))

Error in validObj(t1) : Invalid "track" object:
1: Oooo that's bad A
2: Oooo that's bad B
3: Oooo that's bad C
4: Oooo that's bad D


[Rd] 2 possible bugs in function validObject (PR#7735)
scott.chasalow@bms.com