Janko Thyson
2011-Jun-29 16:36 UTC
[Rd] Ref Classes: bug with using '.self' within initialize methods?
Dear list, I'm wondering if the following error I'm getting is a small bug in the Reference Class paradigm or if it makes perfect sense. When you write an explicit initialize method for a Ref Class, can you then make use of '.self' WITHIN this initialize method just as you would once an object of the class has actually been initialized? Because it seems to me that you can not. Below is an example that shows that calling '.self$someInitFoo()' within the initialize method for 'MyClass' does not work (see section "METHODS" in example below). Instead I have to go with 'someInitFooRefInner(.self=.Object, ...)' (see section "UPDATED METHOD" in example below). Yet, this is only possible because there actually IS such a method (I try to stick to the recommendations at ?setRefClass where it says: "Reference methods should be kept simple; if they need to do some specialized *R* computation, that computation should use a separate *R* function that is called from the reference method") The same problem occurs when, say 'someInitFoo()' calls yet another Ref Class method (as is the case in the example below with a call to '.self$someFoo()'). Is this a desired behavior? Thanks for any clarifying comments! Janko ##### CODE EXAMPLE ##### # CLASSES setRefClass( Class="MyVirtual", contains=c("VIRTUAL"), methods=list( initialize=function(...){ callSuper(...) return(.self) }, someInitFoo=function(flds, ...){ someInitFooRefInner( .self=.self, flds=flds ) } ) ) GENERATOR <- setRefClass( Class="MyClass", contains=c("MyVirtual"), fields=list( A="character", B="numeric" ), methods=list( someFoo=function(...){ someFooRefInner(.self=.self, ...) } ) ) # / # GENERICS setGeneric(name="someInitFooRefInner", def=function(.self, ...) standardGeneric("someInitFooRefInner"), signature=c(".self") ) setGeneric(name="someFooRefInner", def=function(.self, ...) standardGeneric("someFooRefInner"), signature=c(".self") ) # / # METHODS setMethod( f="someInitFooRefInner", signature=signature(.self="MyVirtual"), definition=function(.self, flds, ...){ print("Trying to call '.self$someFoo()") try(.self$someFoo()) print("Trying to call 'someFooRefInner(.self=.self)") try(someFooRefInner(.self=.self)) return(flds) } ) setMethod( f="someFooRefInner", signature=signature(.self="MyVirtual"), definition=function(.self, ...){ print("hello world!") } ) setMethod( f="initialize", signature=signature(.Object="MyVirtual"), definition=function(.Object, GENERATOR=NULL, ...){ # MESSAGE if(class(.Object) == "MyVirtual"){ cat(paste("initializing object of class '", class(.Object), "'", sep=""), sep="\n") } else { cat(paste("initializig object of class'", class(.Object), "' inheriting from class 'MyVirtual'", sep=""), sep="\n") } # / # GET GENERATOR OBJECT if(is.null(GENERATOR)){ GENERATOR <- getRefClass(class(.Object)) } flds <- names(GENERATOR$fields()) .Object$someInitFoo( flds=flds, ... ) return(.Object) } ) # / x <- GENERATOR$new() # UPDATED METHOD setMethod( f="initialize", signature=signature(.Object="MyVirtual"), definition=function(.Object, GENERATOR=NULL, ...){ # MESSAGE if(class(.Object) == "MyVirtual"){ cat(paste("initializing object of class '", class(.Object), "'", sep=""), sep="\n") } else { cat(paste("initializig object of class'", class(.Object), "' inheriting from class 'MyVirtual'", sep=""), sep="\n") } # / # GET GENERATOR OBJECT if(is.null(GENERATOR)){ GENERATOR <- getRefClass(class(.Object)) } flds <- names(GENERATOR$fields()) someInitFooRefInner(.self=.Object, flds=flds, ...) return(.Object) } ) # / x <- GENERATOR$new() [[alternative HTML version deleted]]
John Chambers
2011-Jul-02 20:43 UTC
[Rd] Ref Classes: bug with using '.self' within initialize methods?
I don't have anything to suggest on your specific example but perhaps these two notes are relevant. 1. As is mentioned in the documentation, it's generally a bad idea to write S4 initialize() methods for reference classes, rather than reference class methods for $initialize(): "a reference method is recommended rather than a method for the S4 generic function initialize(), because some special initialization is required for reference objects _before_ the initialization of fields." 2. In a simple example, there is no problem using .self in a $initialize() method. ###### ss <- setRefClass("ss", fields = c("a", "b", "c"), methods = list( initialize = function(...) { callSuper(...) .self$b <- .self$a }, check = function() .self$c <- .self$a )) s1 <- ss$new(a=1) s1$check() stopifnot(identical(s1$a, 1), identical(s1$a, s1$b), identical(s1$a, s1$c)) ####### On 6/29/11 9:36 AM, Janko Thyson wrote:> Dear list, > > I'm wondering if the following error I'm getting is a small bug in the > Reference Class paradigm or if it makes perfect sense. > > When you write an explicit initialize method for a Ref Class, can you > then make use of '.self' WITHIN this initialize method just as you would > once an object of the class has actually been initialized? > Because it seems to me that you can not. > > Below is an example that shows that calling '.self$someInitFoo()' within > the initialize method for 'MyClass' does not work (see section "METHODS" > in example below). Instead I have to go with > 'someInitFooRefInner(.self=.Object, ...)' (see section "UPDATED METHOD" > in example below). Yet, this is only possible because there actually IS > such a method (I try to stick to the recommendations at ?setRefClass > where it says: "Reference methods should be kept simple; if they need to > do some specialized *R* computation, that computation should use a > separate *R* function that is called from the reference method") > > The same problem occurs when, say 'someInitFoo()' calls yet another Ref > Class method (as is the case in the example below with a call to > '.self$someFoo()'). > > Is this a desired behavior? > > Thanks for any clarifying comments! > Janko > > ##### CODE EXAMPLE ##### > > # CLASSES > setRefClass( > Class="MyVirtual", > contains=c("VIRTUAL"), > methods=list( > initialize=function(...){ > callSuper(...) > return(.self) > }, > someInitFoo=function(flds, ...){ > someInitFooRefInner( > .self=.self, > flds=flds > ) > } > ) > ) > GENERATOR<- setRefClass( > Class="MyClass", > contains=c("MyVirtual"), > fields=list( > A="character", > B="numeric" > ), > methods=list( > someFoo=function(...){ > someFooRefInner(.self=.self, ...) > } > ) > ) > # / > > # GENERICS > setGeneric(name="someInitFooRefInner", > def=function(.self, ...) standardGeneric("someInitFooRefInner"), > signature=c(".self") > ) > setGeneric(name="someFooRefInner", > def=function(.self, ...) standardGeneric("someFooRefInner"), > signature=c(".self") > ) > # / > > # METHODS > setMethod( > f="someInitFooRefInner", > signature=signature(.self="MyVirtual"), > definition=function(.self, flds, ...){ > print("Trying to call '.self$someFoo()") > try(.self$someFoo()) > print("Trying to call 'someFooRefInner(.self=.self)") > try(someFooRefInner(.self=.self)) > return(flds) > } > ) > setMethod( > f="someFooRefInner", > signature=signature(.self="MyVirtual"), > definition=function(.self, ...){ > print("hello world!") > } > ) > setMethod( > f="initialize", > signature=signature(.Object="MyVirtual"), > definition=function(.Object, GENERATOR=NULL, ...){ > # MESSAGE > if(class(.Object) == "MyVirtual"){ > cat(paste("initializing object of class '", class(.Object), > "'", > sep=""), sep="\n") > } else { > cat(paste("initializig object of class'", class(.Object), > "' inheriting from class 'MyVirtual'", sep=""), sep="\n") > } > # / > # GET GENERATOR OBJECT > if(is.null(GENERATOR)){ > GENERATOR<- getRefClass(class(.Object)) > } > flds<- names(GENERATOR$fields()) > .Object$someInitFoo( > flds=flds, > ... > ) > return(.Object) > } > ) > # / > > x<- GENERATOR$new() > > # UPDATED METHOD > setMethod( > f="initialize", > signature=signature(.Object="MyVirtual"), > definition=function(.Object, GENERATOR=NULL, ...){ > # MESSAGE > if(class(.Object) == "MyVirtual"){ > cat(paste("initializing object of class '", class(.Object), > "'", > sep=""), sep="\n") > } else { > cat(paste("initializig object of class'", class(.Object), > "' inheriting from class 'MyVirtual'", sep=""), > sep="\n") > } > # / > # GET GENERATOR OBJECT > if(is.null(GENERATOR)){ > GENERATOR<- getRefClass(class(.Object)) > } > flds<- names(GENERATOR$fields()) > someInitFooRefInner(.self=.Object, flds=flds, ...) > return(.Object) > } > ) > # / > > x<- GENERATOR$new() > > [[alternative HTML version deleted]] > > ______________________________________________ > R-devel at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel >