R-alpha: 0.15: `horrible' NextMethod bug (still there...)

Martin Maechler (maechler@stat.math.ethz.ch)
Fri, 20 Dec 96 10:50:48 +0100


Date: Fri, 20 Dec 96 10:50:48 +0100
Message-Id: <9612200950.AA10088@>
From: Martin Maechler <maechler@stat.math.ethz.ch>
To: r-testers@stat.math.ethz.ch
Subject: R-alpha: 0.15: `horrible' NextMethod bug  (still there...)

I sent this over the list, about 2 weeks ago with no real reaction
	(Kurt Hornik confirmed that it happens).
There are actually 2 problems:

1) Whereas infinite recursion is caught properly in R,
	[[ rec <- function(x) rec(x) ; rec(1) ##> stack overflow error ]]
   infinite method dispatching is NOT:

  ## A nice idea of using  OO programming , but BADLY implemented
  print.noquote <- function(obj,...) print(obj, quote = F, ...)

  x <- paste(1:10) ; class(x) <- "noquote"

  print.default(unclass(x), quote = FALSE)
  1] 1  2  3  4  5  6  7  8  9  10
  ##>
  x #-- should give EXACTLY the same (for this x):   >>>>>>> BUT ! <<<<<

  >>> Error: memory exhausted
  >>> Segmentation fault


2) NextMethod (or "class<-" or "class" ??) have (at least) one bug with the
   horrible consequence that a a GLOBAL object is changed... :

####------- save the following in file  nextmeth-bug.R  -----  -----  -----
####------- and type	R < nextmeth-bug.R              -----  -----  -----

###--- My intent was to define a class 'noquote' and print method
###--- which would use the 'quote = FALSE'

print.noquote <- function(obj,...) NextMethod("print",obj, quote = FALSE, ...)

x <- paste(1:10) ; class(x) <- "noquote"

x               ##-- the same as 
print.default(x)

##---- Now, watch this : ---------------------
###----------- This demos a horrible bug in  NextMethod :

print.noquote <- function(obj,...) {
  if(Dbg) cat(" !!_print.noquote: class(obj)= '",
	      paste(class(obj),sep=","), "'\n",sep='')
  if(is.object(obj)) class(obj) <- class(obj)[class(obj) != "noquote"]
  NextMethod("print",obj, quote = FALSE, ...)
}

x <- paste(1:10) ; class(x) <- "noquote" ; Dbg <- FALSE
print.default(x)
x
x
Dbg <- TRUE
x
x #--- so, if Dbg was TRUE, the GLOBAL object x  lost its class attribute !!

## The same happens when  print.noquote is called directly instead of
## via print.default :  
x <- paste(1:10) ; class(x) <- "noquote" ; Dbg <- FALSE
x
print.noquote(x) ##-- get the same error as above...
x
					
##> [1] "1"  "2"  "3"  "4"  "5"  "6"  "7"  "8"  "9"  "10"
##>>>>> I.e.  'x'   LOST it's class attribute !!!!
##            --------------------------------  ERRONOUS assignment to GLOBAL!!
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
r-testers mailing list -- For info or help, send "info" or "help",
To [un]subscribe, send "[un]subscribe"
(in the "body", not the subject !)  To: r-testers-request@stat.math.ethz.ch
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-