From mtmorgan at fhcrc.org  Fri Apr 20 18:20:33 2007
From: mtmorgan at fhcrc.org (Martin Morgan)
Date: Fri, 20 Apr 2007 09:20:33 -0700
Subject: [Rd] setClass inside a function
In-Reply-To: <40A15E1D8A76A949AF0271EF3133E1A9CF7E60@LOWEXPRESS.corp.cefas.co.uk>
	(Iago Mosqueira's message of "Thu, 19 Apr 2007 18:55:35 +0100")
References: <40A15E1D8A76A949AF0271EF3133E1A9CF7E60@LOWEXPRESS.corp.cefas.co.uk>
Message-ID: <6phirbr81bi.fsf@gopher4.fhcrc.org>

Hi Iago --

Here's my attempt at an answer.

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

> Hello,
>
> I would like to create a function that gets passed a class name and
> then calls setClass, and a few other functions, inside. I have done
> this in the past with setmethod, creating accessors for all slots in a
> 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). 

> This does not happen if I redefine the creator function in my working
> environment.

yes, here you are creating the class in the global environment, which
is not locked (!).

> I have attached an example of the kind of function below, and I am
> using R 2.5.0.
>
> Where should I look for information on undertanding what might be
> going on here? Why does this way of working succeeds with setMethod
> but not setClass?

I think that setMethod works because the methods package has already
created an environment within the appropriate name space (try 'ls(<pkg
name space>, all=TRUE)' and look at the '.__<etc>' bindings). What
setMethod does is modfies this environment, rather than the
environment of the name space.

Hope that helps, and is not too misleading.

Martin

> The intention here is to provide an easy way for creating extended
> classes that will inherit from a class already defined, instead of
> array as in the example.
>
> Many thanks,
>
>
> Iago
>
>
> defineClass <- function(name, dimnames) {
> 	# dim, names[2], dimnames[2]
> 	if(names(dimnames)[1] != 'iter')
> 		dimnames <- c(list(iter=1), dimnames)
> 	dim <- unlist(lapply(dimnames, length))
>
> 	# 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))
>
> 	# setClass
> 	setClass(name, representation('array'),
>     	prototype=prototype(array(as.numeric(NA), dim=dim,
> dimnames=dimnames), units='NA'),
> 		validity=validity, where=sys.parent(n=-2))
>
> 	# setValidity
> 	setValidity(name, validity)
>
> 	# constructors
> 	eval(parse(text=paste("setGeneric('", name,
> 		"', function(object, ...) standardGeneric('", name, "'))",
> sep="")))
>
> 	setMethod(name, signature(object='ANY'),
> 		function(object, ...)
> 			return(FLPar(object, ..., class=name))
> 	)
> 	setMethod(name, signature(object='missing'),
> 		function(...) {
> 			return(FLPar(..., class=name))
> 		}
> 	)
>
> }
>
> --- Iago Mosqueira Systems Modelling Cefas Pakefield Rd.  Lowestoft
> NR33 0HT U.K.  Tel +44 (0) 1502 558003
>
>
> ***********************************************************************************
> This email and any attachments are intended for the named\...{{dropped}}



[Rd] setClass inside a function
Martin Morgan