Search code examples
roopreference-class

Order of methods in R reference class and multiple files


There is one thing I really don't like about R reference class: the order you write the methods matters. Suppose your class goes like this:

myclass = setRefClass("myclass",
                       fields = list(
                           x = "numeric",
                           y = "numeric"
                       ))


myclass$methods(
    afunc = function(i) {
        message("In afunc, I just call bfunc...")
        bfunc(i)
    }
)

myclass$methods(
    bfunc = function(i) {
        message("In bfunc, I just call cfunc...")
        cfunc(i)
    }
)


myclass$methods(
    cfunc = function(i) {
        message("In cfunc, I print out the sum of i, x and y...")
        message(paste("i + x + y = ", i+x+y))
    }
)



myclass$methods(
    initialize = function(x, y) {
        x <<- x
        y <<- y
    }
)

And then you start an instance, and call a method:

x = myclass(5, 6)
x$afunc(1)

You will get an error:

Error in x$afunc(1) : could not find function "bfunc"

I am interested in two things:

  • Is there a way to work around this nuisance?
  • Does this mean I can never split a really long class file into multiple files? (e.g. one file for each method.)

Solution

  • Calling bfunc(i) isn't going to invoke the method since it doesn't know what object it is operating on!

    In your method definitions, .self is the object being methodded on (?). So change your code to:

    myclass$methods(
        afunc = function(i) {
            message("In afunc, I just call bfunc...")
            .self$bfunc(i)
        }
    )
    

    (and similarly for bfunc). Are you coming from C++ or some language where functions within methods are automatically invoked within the object's context?

    Some languages make this more explicit, for example in Python a method with one argument like yours actually has two arguments when defined, and would be:

      def afunc(self, i):
      [code]
    

    but called like:

      x.afunc(1)
    

    then within the afunc there is the self variable which referes to x (although calling it self is a universal convention, it could be called anything).

    In R, the .self is a little bit of magic sprinkled over reference classes. I don't think you could change it to .this even if you wanted.