2013-07-03 2 views
3

Мне нужно использовать метод eval, чтобы вызвать метод ссылочного класса. Ниже приведен пример игрушки:Как избежать добавления. При использовании eval в ссылочном классе в R?

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 

Я предполагаю, что я мог сделать eval(parse(text = paste0(".self$", user_defined_text))), но я не очень понимаю:

  • почему .self нужно Eval методов, но не поле?
  • Почему .self больше не нужен после того, как он был использован один раз?
+1

Это похоже на ошибку или, по крайней мере, нежелательное поведение. Обратите внимание, что просто вызывать 'hello' из' p' с 'p $ hello' перед вызовом' p $ run («hello()») также позволяет последнему выполнить без ошибки. 'p $ hello' изменяет среду' p $ run'. Вы можете увидеть это с помощью 'p <- MyClass $ new(); LS (среда (р $ ход)); р $ привет; ls (среда (p $ run)) ' –

+1

@MatthewPlourde Я узнал, что это не ошибка, она предназначена для ленивой оценки для повышения производительности. Несколько полезных ресурсов для других, сталкивающихся с этой проблемой: [R-devel] (https://stat.ethz.ch/pipermail/r-devel/2011-June/061260.html), stackoverflow [вопрос] (http://stackoverflow.com/questions/12543166/reference-classes-tab-completion-and-forced-method-definition?rq=1) – nachocab

ответ

3

«Почему» вопросы всегда сложны для ответа; обычно ответ «потому что». На ?setRefClass мы в конечном счете,

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. 

Я не уверен, что это вполне полезным в случае, когда пользователь по-видимому, в состоянии указать любой способ. Предлагая небольшой непрозрачный редакторский комментарий, я не уверен, «почему» вы хотите написать метод, который будет анализировать входной текст на методы; Я никогда не использовал эту парадигму.

+1

Добавление 'usingMethods (« hello »)' перед 'eval' исправляет эту проблему. Благодаря! – nachocab