From pgilbert902 at gmail.com  Mon Mar 26 15:23:31 2012
From: pgilbert902 at gmail.com (Paul Gilbert)
Date: Mon, 26 Mar 2012 09:23:31 -0400
Subject: [Rd] RC / methods package
In-Reply-To: <4F6F8E50.8020407@gmail.com>
References: <4F6E2EC7.2060001@gmail.com> <4F6E62CB.40109@r-project.org>
	<4F6E6A3F.1050104@gmail.com> <4F6F70D1.4040905@r-project.org>
	<4F6F8E50.8020407@gmail.com>
Message-ID: <4F706DD3.2040001@gmail.com>



On 12-03-25 05:29 PM, Paul Gilbert wrote:
> John
>
> Here is the definition of the TSMySQLConnection class, and a few other
> things. This is a simplified example that produces the message, but
> unfortunately will not work unless you have a MySQL database to connect
> to. (I do get the same problem with PostgreSQL, and may with SQLLite,
> but I have not tested the last yet.)
>
> require("methods")
> require("DBI")
> require("RMySQL")
>
> setClassUnion("OptionalPOSIXct", c("POSIXct", "logical"))
> setClass("conType", representation( drv="character"), "VIRTUAL" )
>
> setClass("TSdb", representation( dbname="character",
> hasVintages="logical", hasPanels="logical"), "VIRTUAL" )
>
>
> setClass("TSMySQLConnection", contains=c("MySQLConnection", "conType",
> "TSdb"))
>
>
> setGeneric("TSconnect", def= function(drv, dbname, ...)
> standardGeneric("TSconnect"))
>
>
> setMethod("TSconnect", signature(drv="MySQLDriver", dbname="character"),
> definition=function(drv, dbname, ...) {
> con <- dbConnect(drv, dbname=dbname, ...)
> new("TSMySQLConnection" , con, drv="MySQL", dbname=dbname,
> hasVintages=dbExistsTable(con, "vintageAlias"),
> hasPanels =dbExistsTable(con, "panels"))
> })
>
> con <- TSconnect(dbDriver("MySQL"), "test")
>
> dbGetQuery(con, "show tables")
> Note: Method with signature "MySQLConnection#integer" chosen for
> function "coerce",
> target signature "TSMySQLConnection#integer".
> "dbObjectId#integer" would also be valid
> Tables_in_test
> 1 A
> 2 B
>  >
>
> The message also seems to go away, even quitting R and restarting to
> clear the cache, if I change the TSconnect method as follow
>
> setMethod("TSconnect", signature(drv="MySQLDriver", dbname="character"),
> definition=function(drv, dbname, ...) {
> con <- dbConnect(drv, dbname=dbname, ...)
> new("TSMySQLConnection" , con, drv="MySQL", dbname=dbname,
> hasVintages=FALSE,
> hasPanels =FALSE)
> })
>
> Why this would happen makes absolutely no sense to me. In the first
> version is dbExistsTable(con, "vintageAlias") left unevaluated in the
> result from new?

This is very strange. With

setMethod("TSconnect",   signature(drv="MySQLDriver", dbname="character"),
    definition=function(drv, dbname, ...) {
         con <- dbConnect(drv, dbname=dbname, ...)
   	hasVintages <- as.logical(dbExistsTable(con, "vintageAlias") )
   	hasPanels   <- as.logical(dbExistsTable(con, "panels") )
	new("TSMySQLConnection" , con, drv="MySQL", dbname=dbname,
   	       hasVintages=FALSE,
   	       hasPanels  =FALSE)
	})

I get the note, but if I remove the two lines that appear to do nothing:

setMethod("TSconnect",   signature(drv="MySQLDriver", dbname="character"),
    definition=function(drv, dbname, ...) {
         con <- dbConnect(drv, dbname=dbname, ...)
	new("TSMySQLConnection" , con, drv="MySQL", dbname=dbname,
   	       hasVintages=FALSE,
   	       hasPanels  =FALSE)
	})

I no longer get the note. I am restarting R each time to be sure nothing 
is cached.

[ R version 2.15.0 RC (2012-03-25 r58832) ]

Paul

>
> As you can tell, I'm struggling a bit with interpreting the information
> from the note. Also, if it were a warning I could set it to stop, and
> then traceback to what was causing the problem. As it is, it took me a
> fairly long time just to get the fact that the call to dbGetQuery() was
> generating the message. And caching the methods may be good for
> performance, but when things change the second time you call them it
> sure makes debugging difficult.
>
> Best,
> Paul
>
>
> On 12-03-25 03:24 PM, John Chambers wrote:
>> On 3/24/12 5:43 PM, Paul Gilbert wrote:
>>>
>>>
>>> On 12-03-24 08:11 PM, John Chambers wrote:
>>>>
>>>>
>>>> On 3/24/12 1:29 PM, Paul Gilbert wrote:
>>>>> (I think this is being caused by the new methods package in RC.)
>>>> Possibly, but the methods package isn't particularly "new" in its
>>>> method
>>>> selection.
>>>>
>>>> We need to see the definition of the class.
>>>
>>> Is there a way to know which class it is that we need to see the
>>> definition for?
>>
>> It's in the note: 'target signature "TSMySQLConnection#integer"'. In
>> functional OOP with multiple dispatch, it's all the classes that matter
>> in general, but in this and most cases, one class is likely the relevant
>> one: "TSMySQLConnection". That was why I said what I did before.
>>
>> (We could go to a bit more effort and back-translate the dispatch string
>> "TSMySQLConnection#integer" into the corresponding formal arguments.
>> Would be more natural with the INSTALL time tool I mentioned before.
>> That's the real challenge here -- to give information about this to the
>> package developer, not the poor user.)
>>
>> John
>>
>>>
>>> Paul
>>>
>>>> The note implies that it
>>>> inherits from both "MySQLConnection" and "dbObjectId", both of which
>>>> have methods for coercing to "integer". Hence the ambiguity.
>>>>>
>>>>> In the RC (March 24) some of my packages are generating a Note
>>>>>
>>>>> Note: Method with signature "MySQLConnection#integer" chosen for
>>>>> function "coerce",
>>>>> target signature "TSMySQLConnection#integer".
>>>>> "dbObjectId#integer" would also be valid
>>>>>
>>>>> This is coming from a call to dbGetQuery() in package DBI. The method
>>>>> with the signature "TSMySQLConnection#integer" is generated
>>>>> automatically because TSMySQLConnection inherits from
>>>>> MySQLConnection. (More details below.)
>>>>>
>>>>> Is there a way to pass this information along to coerce when the
>>>>> method is generated, or otherwise suppress the Note?
>>>> No. Methods are inherited according to rules implied by the class
>>>> inheritance; R doesn't allow you to override the inheritance, other
>>>> than
>>>> by being more explicit about the method definition. (It's only a note,
>>>> and IMO a relevant one. Be glad the language isn't Dylan, which treats
>>>> similar ambiguities as a programming error. :-))
>>>>>
>>>>> BTW,
>>>>> 1/ It would be nice if the Note mentioned what method is generating
>>>>> it, in addition to the signature. Debugging for a call several levels
>>>>> deep in the stack is already hard enough.
>>>> ?? it does, for coerce() which admittedly you have to know is the
>>>> method
>>>> defined for as(thing, "integer") either directly or indirectly. Unless
>>>> you mean showing you the whole method definition, but that seems not
>>>> relevant to selection.
>>>>
>>>> If you wanted to see the coerce() method, you need to do
>>>> showMethods("coerce"), but I don't think that's relevant. As mentioned,
>>>> it's the class hierarchy that matters.
>>>>>
>>>>> 2/ The note only seems to get generated on the first call and then
>>>>> gets suppressed. This will be nice for users, but makes debugging
>>>>> harder. Is there a way to prevent suppressing the message?
>>>> No. the note is generated when an inherited method is found. That
>>>> method
>>>> is then cached, so the computations required are (fortunately) not
>>>> repeated.
>>>>
>>>> It would be nice to have tools that the package writer could apply to
>>>> generate all possible inheritance patterns, and flag possible
>>>> ambiguities at package INSTALL time, as opposed to when the package is
>>>> used. But it's likely that would generate so many cases unlikely to
>>>> occur that the package developer would ignore it, even assuming the
>>>> developer was energetic enough to use the tool in the first place.
>>>>> o
>>>>> 3/ It seems strange that getMethod() cannot find the methods even
>>>>> though showMethods() shows it. (See below.)
>>>> I think you're confusing getMethod(), which only finds directly defined
>>>> methods, with selectMethod() which replicates the inheritance
>>>> computations.
>>>>
>>>> In any case the selection of the method has been specified for you
>>>> already.
>>>>
>>>> John
>>>>>
>>>>> Paul
>>>>> ________
>>>>>
>>>>> >showMethods("dbGetQuery")
>>>>> Function: dbGetQuery (package DBI)
>>>>> conn="MySQLConnection", statement="character"
>>>>>
>>>>> > z <- TSget("Series 1", con, TSrepresentation="timeSeries")
>>>>> Note: Method with signature "MySQLConnection#integer" chosen for
>>>>> function "coerce",
>>>>> target signature "TSMySQLConnection#integer".
>>>>> "dbObjectId#integer" would also be valid
>>>>> Loading required package: zoo
>>>>>
>>>>> Attaching package: ?zoo?
>>>>>
>>>>> The following object(s) are masked from ?package:timeSeries?:
>>>>>
>>>>> time<-
>>>>>
>>>>> The following object(s) are masked from ?package:base?:
>>>>>
>>>>> as.Date, as.Date.numeric
>>>>>
>>>>> > showMethods("dbGetQuery")
>>>>> Function: dbGetQuery (package DBI)
>>>>> conn="MySQLConnection", statement="character"
>>>>> conn="TSMySQLConnection", statement="character"
>>>>> (inherited from: conn="MySQLConnection", statement="character")
>>>>>
>>>>> > getMethod("dbGetQuery", signature = c("TSMySQLConnection",
>>>>> statement="character"))
>>>>> Error in getMethod("dbGetQuery", signature = c("TSMySQLConnection",
>>>>> statement = "character")) :
>>>>> No method found for function "dbGetQuery" and signature
>>>>> TSMySQLConnection, character
>>>>> >
>>>>>
>>>>> ______________________________________________
>>>>> R-devel at r-project.org mailing list
>>>>> https://stat.ethz.ch/mailman/listinfo/r-devel
>>>>>
>>>



[Rd] RC / methods package
Paul Gilbert