From sfalcon at fhcrc.org  Mon Apr 16 01:51:39 2007
From: sfalcon at fhcrc.org (Seth Falcon)
Date: Sun, 15 Apr 2007 16:51:39 -0700
Subject: [Rd] as() creates invalid entries in methods list?
Message-ID: <m2fy71dwms.fsf@fhcrc.org>

Hi,

We've observed rather strange behavior related to as().  When as() is
used to make a conversion to a super class, an invalid entry is
inserted into the table of methods.

   > setClass("A", contains="list")
   > get(".MTable", environment(coerce))[["list#A"]]
   NULL

   > as(list(), "A")
   > get(".MTable", environment(coerce))[["list#A"]]
   function (from, to) 
   {
       obj <- new("A")
       as(obj, "list") <- from
       obj
   }
   <environment: namespace:methods>

Entries in .MTable should be MethodDefinition objects (or at least
that is what is usually there for methods defined via setAs).  It
happens that if you try to load a package that has a NAMESPACE file
with a directive exportMethods(coerce) but no call to setAs then you
get an error:

   library("hello")
   Error in .mergeMethodsTable(generic, mtable, get(tname, envir = env),  : 
           Invalid object in meta table of methods for "coerce", label "list#A", had class "function"

So I think there are two problems that might need fixes:

1. methods::as shouldn't create invalid entries.  I've included a
   patch (see below) that seems to help, but I'm not sure it is the
   right fix.  For example, there are two helper functions that create
   coerce methods and perhaps a better fix is for both of these to be
   modified to return MethodDefinition objects.

2. The name space code allows packages to have methods listed in
   exportMethods directives even if no corresponding setMethod,
   setGeneric, or setAs call appears in the R code.  Ideally, a
   warning or error would be raised in this case.  I'm not sure such a
   declaration should do any harm in theory, but in practice it seems
   to trigger subtle bugs in the methods package.

+ seth

--- a/src/library/methods/R/as.R
+++ b/src/library/methods/R/as.R
@@ -37,9 +37,6 @@ as <-
                   test <- ext at test
                   asMethod <- .makeAsMethod(ext at coerce, ext at simple, Class, Clas
                   canCache <- (!is(test, "function")) || identical(body(test), 
-                  if(canCache) { # make into method definition
-                    asMethod <- .asCoerceMethod(asMethod, sig, FALSE)
-                  }
                 }
             }
             if(is.null(asMethod) && extends(Class, thisClass)) {
@@ -54,6 +51,10 @@ as <-
                                          fdef = coerceFun, mlist =
                                          coerceMethods)
                 inherited <- TRUE
+            } else {
+                if(canCache) { # make into method definition
+                    asMethod <- .asCoerceMethod(asMethod, sig, FALSE)
+                }
             }
             ## cache in the coerce function's environment
             if(canCache && !is.null(asMethod)) {



-- 
Seth Falcon | Computational Biology | Fred Hutchinson Cancer Research Center
http://bioconductor.org



[Rd] as() creates invalid entries in methods list?
Seth Falcon