добавить класс глобального объекта S3 в функцию, избегая оператора `<< -` - PullRequest
0 голосов
/ 04 декабря 2018

Я определяю объект S3 внутри функции и присваиваю его переменной в глобальной среде;впоследствии в той же функции я добавляю к ней дополнительный класс.Единственный способ, которым я смог это сделать, - это использовать оператор <<-, которого я предпочел бы избежать, поскольку при чтении он фактически назначает родительскую среду, и это может быть опасно.В идеале я хотел бы использовать assign, но первый аргумент - это имя переменной, поэтому он не работает.Любые предложения о том, как это может быть лучше достигнуто без использования <<-?

Для записи я также попробовал обычный оператор присваивания <-, но это также не помогает, и я не понимаю, почему, так как переменнаяуже определены глобально.

Некоторые иллюстративные примеры ниже:

# <<- assigns to parent environment, if "lucky" that is the globalenv, me no gusto :(
foo_works_dragons <- function(addclass) {
  fooobj <- structure(list(), class = "Alpha")
  assign("G_FOOOBJ", fooobj, envir = globalenv())
  class(G_FOOOBJ) <<- c(class(G_FOOOBJ), addclass)
  return(TRUE)
}


# prefer assign statement but function argument x is "a variable name" from man page, so ok not working, any suggestions?
foo_fails_nodragons <- function(addclass) {
  fooobj <- structure(list(), class = "Alpha")
  assign("G_FOOOBJ", fooobj, envir = globalenv())
  assign("class(G_FOOOBJ)", c(class(G_FOOOBJ), addclass), envir = globalenv())
  return(TRUE)
}


# fails, don't understand though why
foo_fails_but_why <- function(addclass) {
  fooobj <- structure(list(), class = "Alpha")
  assign("G_FOOOBJ", fooobj, envir = globalenv())
  class(G_FOOOBJ) <- c(class(G_FOOOBJ), addclass)
  return(TRUE)
}


foo_works_dragons("Beta")
print(class(G_FOOOBJ))
# [1] "Alpha" "Beta"
rm(G_FOOOBJ)

foo_fails_nodragons("Beta")
print(class(G_FOOOBJ))
# [1] "Alpha"
rm(G_FOOOBJ)

foo_fails_but_why("Beta")
print(class(G_FOOOBJ))
# [1] "Alpha"
rm(G_FOOOBJ)

1 Ответ

0 голосов
/ 04 декабря 2018

Используйте envir $ обозначение объекта:

foo <- function(addclass, envir = .GlobalEnv) {
  envir$G_FOOOBJ <- structure(list(), class = "Alpha")
  class(envir$G_FOOOBJ) <- c(class(envir$G_FOOOBJ), addclass)
  return(TRUE)
}

if (exists("G_FOOOBJ")) rm(G_FOOOBJ)
foo("Beta")
## [1] TRUE

G_FOOOBJ
## list()
## attr(,"class")
## [1] "Alpha" "Beta" 

Если вы действительно хотите использовать assign, тогда это работает:

foo2 <- function(addclass, envir = .GlobalEnv) {
  fooobj <- structure(list(), class = "Alpha")
  assign("G_FOOOBJ", structure(fooobj, class = c(class(fooobj), addclass)), envir)
  return(TRUE)
}

if (exists("G_FOOOBJ")) rm(G_FOOOBJ)
foo2("Beta")
## [1] TRUE

G_FOOOBJ
## list()
## attr(,"class")
## [1] "Alpha" "Beta" 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...