R: Изменение объекта S4 из метода S4 - PullRequest
0 голосов
/ 14 февраля 2020

У меня есть объект S4, который представляет рекурсивную древовидную структуру, содержащую некоторые данные и другие объекты того же класса. У меня также есть рекурсивная функция для изменения двух слотов в каждом узле дерева. Функция (назовите ее «копирование ()») делает свое дело правильно, когда я делаю это:

> obj <- treeObj(4, 5)
> slotNames(obj)
[1] "x" "y" "listOfOtherTreeObjs"
> obj <- propagate(obj, 1, 4)  

Я могу написать такую ​​функцию, которая принимает аргумент и заполняет дерево этими данными, нет проблем .

Однако я хочу, чтобы у меня была возможность вызывать распространения () из метода объекта root:

setMethod("transform", signature="treeObj",
    definition=function(object, i, j) {
         object@x <- i;  object@y <- j;
         object <- propagate(object, i, j);
         ... (do some other stuff in the tree)
    })

В этом методе распространение () кажется функционировать как следует, но его результат, по-видимому, не присваивается родительскому объекту способом, который можно обнаружить в определении метода transform (). Мои вопросы:

  1. Я предполагаю, что это связано с природой вызова по значению R, и я не могу влиять на значение объекта, который использовался для вызова функции преобразования. Это правильно, или я просто глуп, и это должно сработать?

  2. Есть ли R magi c, чтобы обойти это? Какой-нибудь способ вызвать функцию assign (), чтобы заставить новое определение объекта заменить текущее? Или что-то?

  3. Есть ли еще Ri sh способ создания моего рекурсивного объекта для поддержки такого рода вещей?

Спасибо в заранее.

1 Ответ

1 голос
/ 14 февраля 2020

Есть две вещи, которые необходимо сделать, чтобы эта работа:

1) предположительно, рекурсия не включается go навсегда, т.е. в какой-то момент объект не будет содержать ссылку на другой объект, потому что он находится в нижней части дерева. Таким образом, вам нужна возможность того, что список другого дерева ob js равен NULL. Вы делаете это с объединением классов:

setClassUnion("listOfOtherTreeObjsOrNULL",c("listOfOtherTreeObjs","NULL"))

, а затем правильный класс для использования в третьем слоте вашего объекта - это новый союз классов.

2), когда вы определяете метод для transform должен выглядеть примерно так:

function(object,i,j){
  ## do whatever you want with i and j
  if(is.null(object@listOfOtherTreeObjs)) return(object)
  else{
    object@listOfOTherTreeObjs <- lapply(object@listOfOtherTreeObjs,propagate)
    return(object)
  }
}

Причина, по которой ваши изменения, похоже, не дали никакого эффекта, заключается в том, что вы ничего не return извлекали из своей функции, поэтому вы меняли только копии ваших объектов, которые нигде не сохранялись.

...