Tengfei Yin
2011-Jun-08 23:38 UTC
[Rd] Reference Class error message: may be caused by lazy evaluation?
Dear All, I came across an error message recently when constructing a reference class, an example is attached below, it looks like only if I call a specific method in advance, otherwise it cannot be found in defined method without using .self, this make it difficulty that sometimes in my initialize method, I need to call other method defined in the same reference class, the workaround for this is add .sef to it. ############### example begin ############################ setRefClass("testclass", fields = list(a = "numeric"), methods = list( addOne = function(){ a <<- a+1 print(a) }, add = function(){ addOne() }, show = function(){ print(addOne) }, showself = function(){ print(.self$addOne) } )) obj <- new("testclass", a = 1) obj$show() # Error in print(addOne) : object 'addOne' not found obj$addOne() # return 2, works obj$show() # after calling addOne(), show() works ## works if use .self$... obj2 <- new("testclass", a = 1) obj2$showself() ## works when call the method directly within another method obj3 <- new("testclass", a = 1) obj3$add() ################ end ########################################## I am still learning this new technique, if I made any mistake I didn't notice before, please let me know, I will really appreciate that. Thanks a lot! Tengfei -- Tengfei Yin MCDB PhD student 1620 Howe Hall, 2274, Iowa State University Ames, IA,50011-2274 Homepage: www.tengfei.name [[alternative HTML version deleted]]
John Chambers
2011-Jun-09 17:11 UTC
[Rd] Reference Class error message: may be caused by lazy evaluation?
Good catch. Here's the problem. To save space and time, reference methods are not all copied to every object in the class. Instead, the methods are copied in when first accessed. Methods are functions which use the object as their environment. So that is the sense in which "lazy evaluation" is involved. If a method calls another method (add() calling addOne() in your example), then the method for the `$` operator knows to copy over that method (addOne). (The second of my examples below shows this.) But if the method _refers_ to another method without calling it, the code analysis does not currently catch the reference. We can fix that, although it's a little subtle. Meanwhile, your showself() is a good workaround. For anyone interested, the code below illustrates. One point of style. I would suggest saving the generator object and calling its $new() method, as below, rather than treating the reference class as an S4 class. The result is identical AFAIK, but the style is more typical of such OOP languages. John --------------------------- > tc <- setRefClass("testclass", fields = list(a = "numeric"), + methods = list( .... + )) > t1 <- tc$new(a=1) > ss = t1$show > ss Class method definition for method show() function () { print(addOne) } <environment: 0x10188d5f8> > ev = environment(ss) > ev <environment: 0x10188d5f8> > t1 An object of class "testclass" <environment: 0x10188d5f8> # <<<< same environment > objects(ev) [1] "a" "show" #<<<< not addOne, though > t1$addOne Class method definition for method addOne() function () { a <<- a + 1 print(a) } <environment: 0x10188d5f8> > objects(ev) [1] "a" "addOne" "show" # <<<< now addOne is there On 6/8/11 4:38 PM, Tengfei Yin wrote:> Dear All, > > I came across an error message recently when constructing a reference class, > an example is attached below, it looks like only if I call a specific method > in advance, otherwise it cannot be found in defined method without using > .self, this make it difficulty that sometimes in my initialize method, I > need to call other method defined in the same reference class, the > workaround for this is add .sef to it. > > > ############### example begin ############################ > setRefClass("testclass", fields = list(a = "numeric"), > methods = list( > addOne = function(){ > a<<- a+1 > print(a) > }, > add = function(){ > addOne() > }, > show = function(){ > print(addOne) > }, > showself = function(){ > print(.self$addOne) > } > )) > > obj<- new("testclass", a = 1) > obj$show() # > Error in print(addOne) : object 'addOne' not found > obj$addOne() # > return 2, works > obj$show() # > after calling addOne(), show() works > > ## works if use .self$... > obj2<- new("testclass", a = 1) > obj2$showself() > > ## works when call the method directly within another method > obj3<- new("testclass", a = 1) > obj3$add() > > ################ end ########################################## > > I am still learning this new technique, if I made any mistake I didn't > notice before, please let me know, I will really appreciate that. > > Thanks a lot! > > Tengfei >
Reasonably Related Threads
- Creating a reference class object from a class definition in a package fails
- Reference Classes: Generalizing Reference Class Generator objects?
- Test on mu with multivariate normal distribution
- Internally accessing ref class methods with .self$x is different from .self[['x']]
- how to manipulate object in specific environment?