Присвоение значений полям в ссылочных классах R - PullRequest
0 голосов
/ 09 мая 2020

Я создал пакет, в значительной степени основанный на ссылочных классах. Ответ, который я получил от члена команды CRAN после его отправки, заключался в том, что я не мог использовать <- в пакете (<code>"Please make sure you are not modifying the global environment (f.i. by using <<-"). Оказалось, что это недоразумение (<-- изменяет поле в среде, принадлежащей только эталонному классу, а не глобальную среду), но меня заинтересовали альтернативы <<-. Я нашел по крайней мере еще один способ присвоения значений полям ссылочного класса, который дает ту же функциональность, что и << - и он "кажется работает", если я использую <code>.self для ссылки на поле и назначаю с помощью <- вместо <--. Например, вместо

#' A general purpose linked stack
#'

#' @export Stack
#' @exportClass Stack
Stack <- setRefClass(
  Class="Stack",
  fields = list(
    #' @field size the size of the stack (number of elements in the stack)
    m_size = "integer",
    #' @field stackNode an envronment containing the current element and the one under
    m_stackNode = "ANY"
  ),
  methods = list(

    initialize = function (...) {
      m_size <<- 0L
    },

    isEmpty = function() {
      if (m_size == 0) {
        return(TRUE)
      } else {
        return(FALSE)
      }
    },

    createEmptyEnvironment = function() {
      emptyenv()
    },

    createNode = function(val, nextNode = NULL) {
      node <- new.env(parent=createEmptyEnvironment())
      node$element <- val
      node$nextNode <- nextNode
      node
    },

    push = function(val) {
      "Add an element to the top of the stack"
      if(isEmpty()) {
        m_stackNode <<- createNode(val)
      } else {
        m_stackNode <<- createNode(val, m_stackNode)
      }
      m_size <<- (m_size + 1L)
    },

    pop = function() {
      "Pull the top element from the stack removing it from the stack"
      if(!isEmpty()) {
        currentNode <- m_stackNode$element
        m_stackNode <<- m_stackNode$nextNode
        m_size <<- (m_size - 1L)
        return(currentNode)
      }
    },

    peek = function() {
      "Get the top element from the stack without changing it"
      if(!isEmpty()) {
        return(m_stackNode$element)
      }
    },

    size = function() {
      "Get the current size of the stack"
      m_size
    }
  )
)

я могу сделать это:

#' A general purpose linked stack
#'

#' @export Stack
#' @exportClass Stack
Stack <- setRefClass(
  Class="Stack",
  fields = list(
    #' @field size the size of the stack (number of elements in the stack)
    m_size = "integer",
    #' @field stackNode an envronment containing the current element and the one under
    m_stackNode = "ANY"
  ),
  methods = list(

    initialize = function (...) {
      .self$m_size <- 0L
    },

    isEmpty = function() {
      if (m_size == 0) {
        return(TRUE)
      } else {
        return(FALSE)
      }
    },

    createEmptyEnvironment = function() {
      emptyenv()
    },

    createNode = function(val, nextNode = NULL) {
      node <- new.env(parent=createEmptyEnvironment())
      node$element <- val
      node$nextNode <- nextNode
      node
    },

    push = function(val) {
      "Add an element to the top of the stack"
      if(isEmpty()) {
        .self$m_stackNode <- createNode(val)
      } else {
        .self$m_stackNode <- createNode(val, m_stackNode)
      }
      .self$m_size <- (m_size + 1L)
    },

    pop = function() {
      "Pull the top element from the stack removing it from the stack"
      if(!isEmpty()) {
        currentNode <- m_stackNode$element
        .self$m_stackNode <- m_stackNode$nextNode
        .self$m_size <- (m_size - 1L)
        return(currentNode)
      }
    },

    peek = function() {
      "Get the top element from the stack without changing it"
      if(!isEmpty()) {
        return(m_stackNode$element)
      }
    },

    size = function() {
      "Get the current size of the stack"
      m_size
    }
  )
)

Есть ли проблема с этим (обходным) подходом, всегда ли он будет означать одно и то же при таком использовании? Есть также field(name, value), который, кажется, делает то же самое ... это просто разные способы снять шкуру с кошки?

...