Справочный класс R: метод копирования с активными привязками

Похоже метод копирования не работает, если у вас активная привязка.

Пример класса:

test <- setRefClass("test", fields = list(x =function() y + 1 , y = "numeric"))

Инициализация работает нормально:

a <- test(y = 1)
a$x
[1] 2
a$y
[1] 1

Ошибка при копировании:

a$copy()
Error in (function ()  : unused argument (quote(2))

Это ожидаемое поведение?

R.version
platform       x86_64-w64-mingw32          
arch           x86_64                      
os             mingw32                     
system         x86_64, mingw32             
status                                     
major          3                           
minor          1.2                         
year           2014                        
month          10                          
day            31                          
svn rev        66913                       
language       R                           
version.string R version 3.1.2 (2014-10-31)
nickname       Pumpkin Helmet   

person Carlos Cinelli    schedule 22.01.2016    source источник
comment
Активные привязки должны иметь форму function(value) {} для возможности назначения; copy() пытается установить для поля старое значение.   -  person Martin Morgan    schedule 23.01.2016
comment
Большое спасибо @MartinMorgan! Однако такое поведение все еще кажется немного странным, потому что активные привязки без аргументов довольно распространены! Основываясь на вашем ответе, я создал метод копирования, который не пытается присваивать значения активным привязкам, пожалуйста, не стесняйтесь исправлять мой ответ, если это необходимо!   -  person Carlos Cinelli    schedule 24.01.2016


Ответы (1)


Судя по комментарию Мартина, проблема заключается в части assign() метода copy по умолчанию:

 for (field in names(def@fieldClasses)) {
        if (shallow) 
            assign(field, get(field, envir = selfEnv), envir = vEnv)
        else {
            current <- get(field, envir = selfEnv)
            if (is(current, "envRefClass")) 
                current <- current$copy(FALSE)
            assign(field, current, envir = vEnv)
        }
    }

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

test <- setRefClass("test", fields = list(x = function(...) y + 1 , y = "numeric"))

Теперь метод копирования работает нормально. Но функция не выдает ошибку, если вы пытаетесь присвоить значения активным привязкам (иногда это то, что мне нужно в случаях использования, которые у меня есть).

Поэтому другое решение, которое я пробовал, состояло в том, чтобы переопределить метод копирования, выполняющий цикл for только для тех полей, которые не являются активными привязками:

test <- setRefClass("test", fields = list( x = function() y + 1, y = "numeric"))

test$methods(copy = function (shallow = FALSE) 
{
  def <- .refClassDef
  value <- new(def)
  vEnv <- as.environment(value)
  selfEnv <- as.environment(.self)
  fields <- names(def@fieldClasses)[def@fieldClasses!=  "activeBindingFunction"]
  for (field in fields) {
    if (shallow) 
      assign(field, get(field, envir = selfEnv), envir = vEnv)
    else {
      current <- get(field, envir = selfEnv)
      if (is(current, "envRefClass")) 
        current <- current$copy(FALSE)
      assign(field, current, envir = vEnv)
    }
  }
  value
}
)

Кажется, он работает нормально в случаях, которые я тестировал. Я не проверял это полностью, поэтому я не знаю, сломается ли он в других случаях.

person Carlos Cinelli    schedule 24.01.2016