From iago.mosqueira at gmail.com  Tue Apr 24 11:37:46 2007
From: iago.mosqueira at gmail.com (Iago Mosqueira)
Date: Tue, 24 Apr 2007 11:37:46 +0200
Subject: [Rd] setClass inside a function
Message-ID: <dba1e14b0704240237x666ffeabha325659b1d194b68@mail.gmail.com>

Hi Martin,



Thanks very much, your suggestion on the "where" argument did the trick.



Many thanks,





Iago



>

> "Iago Mosqueira (Cefas)" <Iago.Mosqueira at cefas.co.uk> writes:

>

> > Hi Martin,

> >

> > Thanks very much for your help.

> >

> >> Hi Iago --

> >>

> >> Here's my attempt at an answer.

> >>

> >> "Iago Mosqueira (Cefas)" <Iago.Mosqueira at cefas.co.uk> writes:

> >>

> >> > set of S4 classes. But setClass is choking when my function

> >> is called

> >> > isnide a package, telling about an error in

> exists(cname, where). I

> >> > assume this to be a problem with the environment where

> the class is

> >> > created. If I define my creator function in a package

> and load it,

> >> > when I call it I get

> >> >

> >> > Error in assign(mname, def, where): cannot add bindings

> to a locked

> >> > environment

> >>

> >> You're trying to create a class in the package name space, and the

> >> name space is locked (cannot be modified) after the package is

> >> loaded. If your intention is programmatically generate

> static classes

> >> (in a kind of macro-like way) then I think you could still use this

> >> approach but ensure that the classes are created when the

> package is

> >> loaded (e.g., by including a class creation function that

> is actually

> >> evaluated, not just defined, in your package code).

> >

> > Yes, I have tried that. Inmediatly after the creator function is

> > defined I use it to create a new class. And this class is exported

> > in the package NAMESPACE. Still, it says the package environment is

> > locked, although the call to setClass is part of the package.

>

> Try removing the 'where' argument in setClass; or replacing it with

> topenv(parent.frame()) -- the top environment when the package is

> loaded is the name space.

>

> Also, for fun,

>

> >> > 	# validity

> >> > 	foo <- "validity <- function(object) {"

> >> > 	# foo <- c(foo, "browser()")

> >> > 	foo <- c(foo, paste("if(all(names(dimnames(object)) != c('",

> >> > 		paste(names(dimnames), collapse="','", sep=""), "')))",

> >> > sep=""))

> >> > 	foo <- c(foo, "stop(paste('dimnames are not correct for class',

> >> > name))")

> >> > 	foo <- c(foo, "return(TRUE)}")

> >> > 	eval(parse(text=foo))

>

> you can write something like

>

>     validity <- function (object) {

>         msg <- NULL

>         cat("checking", name, "/", class(object), "validity\n")

>         if (all(names(dimnames(object)) != c("iter", "y")))

>             msg <- paste("dimnames are not correct for class", name)

>         if (is.null(msg)) TRUE

>         else msg

>     }

>

> and continue to include validity=validity in setClass. This will use

> R's lexical scope to figure out the correct name, etc for each class

> created. Note also that the idea is that the validity function either

> returns TRUE or a character string, not itself calling 'stop'.

>

> >> > 	# constructors

> >> > 	eval(parse(text=paste("setGeneric('", name,

> >> > 		"', function(object, ...) standardGeneric('",

> >> name, "'))",

> >> > sep="")))

>

> I had expected that

>

>     setGeneric(name,

>                function(object, ...) standardGeneric(name))

>

> would work, but apparently not. This might be a bit cleaner way to

> create complcated substitutions;

>

>     eval(substitute({

>         setGeneric(NAME,

>                    function(object, ...) {

>                        standardGeneric(NAME)

>                    })

>         }, list(NAME=name)))

>

> >> > 	setMethod(name, signature(object='missing'),

> >> > 		function(...) {

> >> > 			return(FLPar(..., class=name))

> >> > 		}

> >> > 	)

>

> It's a bit surprising that this setMethod works, as the function

> signature is different from the generic. This might cause problems

> further down the line. I would have thought that the correct

> formulation would be along the lines of

>

>     setMethod(name, signature(object='missing'),

>               function(object, ...) {

>                   FLPar(..., class=name)

>               })

>

> Martin

> --

> Martin Morgan

> Bioconductor / Computational Biology

> http://bioconductor.org

>



[Rd] setClass inside a function
Iago Mosqueira