Search code examples
rreference-class

How to avoid prepending .self when using eval in a reference class in R?


I need to use eval to call a reference class method. Below is a toy example:

MyClass <- setRefClass("MyClass",

    fields = c("my_field"),

    methods = list(

        initialize = function(){
            my_field <<- 3
        },

        hello = function(){
            "hello"
        },

        run = function(user_defined_text){
            eval(parse(text = user_defined_text))
        }
    )
)

p <- MyClass$new()
p$run("hello()") # Error: could not find function "hello" - doesn't work
p$run(".self$hello()") # "hello" - it works
p$run("hello()") # "hello" - now it works?!

p <- MyClass$new()
p$run("my_field") # 3 - no need to add .self

I guess I could do eval(parse(text = paste0(".self$", user_defined_text))), but I don't really understand:

  • why is .self needed to eval methods, but not fields?
  • why is .self no longer needed after it has been used once?

Solution

  • 'Why' questions are always challenging to answer; usually the answer is 'because'. On ?setRefClass we eventually have

    Only methods actually used will be included in the environment
    corresponding to an individual object.  To declare that a method
    requires a particular other method, the first method should
    include a call to '$usingMethods()' with the name of the other
    method as an argument. Declaring the methods this way is essential
    if the other method is used indirectly (e.g., via 'sapply()' or
    'do.call()'). If it is called directly, code analysis will find
    it. Declaring the method is harmless in any case, however, and may
    aid readability of the source code.
    

    I'm not sure this is entirely helpful in your case, where the user is apparently able to specify any method. Offering a little unasked editorial comment, I'm not sure 'why' you'd want to write a method that would parse input text to methods; I've never used that paradigm myself.