0

I am writing a class definition that will be extremely long, and I'd like to source the code for the methods from separate files. Most of the time, that seems to work, but I have encountered something strange when trying to return a data.frame. When the code is written directly in the class definition, the data.frame returns fine. When it is sourced, what gets returned is a list of length 2, where the first element (named value) contains the data.frame, and the second element (named visible) contains an atomic logical TRUE. How can I get the method to return just the data.frame while leaving the code for the method in a separate file?

Here is the main file:

#MainScript.R
library(R6)

MyClass = R6Class(
  classname = "myclass",
  private = list(Frame = NA),
  public = list(
    initialize = function(){},
    setFrame = function(x){private$Frame = x},
    getFrame = function(){
      MyData = private$Frame
      return(MyData)
    },
    getFrame2 = function(){source("getFrame2.R", local = T)}
  )
)


data1 = data.frame(v1 = rnorm(5,1,2), v2 = rnorm(5,1,2))

current = MyClass$new()
current$setFrame(data1)
current$getFrame()
current$getFrame2()

Here is the method source file:

#getFrame2.R

MyData = private$Frame
return(MyData)

Note that the code for the two methods is exactly the same. The code can be downloaded from github.

Paul de Barros
  • 1,170
  • 8
  • 22
  • 2
    This is not really how `source()` is meant to be used. This will also get very complicated if your current working directory is different than the place where these two files are located. Instead look into making a proper package in R in order to distribute related code across multiple files. Or at the very least put proper functions in the file you are sourcing and source them at the top of your file and use them in your code as proper objects. – MrFlick Apr 10 '17 at 17:47
  • Also `return` is only meant to be used for returning at the end of a function - using it at the top level in a source file doesn't make sense. – Dason Apr 10 '17 at 17:48
  • @MrFlick - will that work if the functions are intended to be methods that will reference private and self members and methods of the class instance? – Paul de Barros Apr 10 '17 at 18:01
  • Just define a function that takes the private data as parameters and call that from the class definition. – MrFlick Apr 10 '17 at 18:02
  • @Dason - that was done because sourcing the entire method definition didn't seem to work. The `return` statement is the end of the code that is contained within the method (function) definition, so it does execute at the end of the method (function). – Paul de Barros Apr 10 '17 at 18:03
  • PauldeBarros Right but as @MrFlick points out... that's not how `source` is meant to be used (and I don't think it's doing what you think it is). – Dason Apr 10 '17 at 18:09

1 Answers1

0

As MrFlick suggested, the easy way to accomplish this is by defining a function that does what you want the method to do, and then defining the method as a call to that function, passing the required members of the class instance as parameters.

The function definition:

#getFrame3.R
getFrame3 = function(Frame){
  MyData = Frame
  return(MyData)
}

The main file:

#MainScript3.R
library(R6)
source("getFrame3.R")

MyClass = R6Class(
  classname = "myclass",
  private = list(Frame = NA),
  public = list(
    initialize = function(){},
    setFrame = function(x){private$Frame = x},
    getFrame = function(){
      MyData = private$Frame
      return(MyData)
    },
    getFrame2 = function(){source("getFrame2.R", local = T)},
    getFrame3 = function(){return(getFrame3(private$Frame))}
  )
)

data1 = data.frame(v1 = rnorm(5,1,2), v2 = rnorm(5,1,2))

current = MyClass$new()
current$setFrame(data1)
current$getFrame() #works with code in the class definition
current$getFrame2() #doesn't work
current$getFrame3() #works with function call
Community
  • 1
  • 1
Paul de Barros
  • 1,170
  • 8
  • 22