функция make R возвращает заблокированный / неизменный список - PullRequest
2 голосов
/ 09 ноября 2019

У меня есть функция, которая возвращает список. Мне бы хотелось, чтобы этот список был неизменным, подобно тому, как lockBinding предотвращает перезапись или редактирование объекта.

Это будет выглядеть примерно так:

myfun <- function(x){
    out <- list(a = 1, val = x)
    make_read_only(out)
    out
}
test <- myfun(9)
test$a
[1] 1

test$val
[1] 9

test
$a
[1] 1

$val
[1] 9

test$newval <- 7
Error:

Где make_read_only() - это просто standin для функции или некоторого кода, который выполняет эту задачу.

У меня естьпопытался использовать lockBinding, который отлично работал бы, однако «замок» не выживал, передаваясь вверх в родительскую среду после того, как функция вернула свой вывод. Я также рассмотрел попытку заблокировать символ в родительской среде, но, похоже, не существует способа узнать, чему будет присвоен вывод изнутри функции, что необходимо в качестве аргумента lockBinding.

Кажется, что может быть способ сделать это, возвращая ссылку на среду и блокируя среду с помощью lockEnvironment () или делая что-то подобное, но я хотел бы услышать, какие есть варианты для достижения этой цели, прежде чем начать,Похоже, что это может быть достижимо с помощью R6, но я бы предпочел избегать использования R6, поскольку он не требуется для любой другой части этой кодовой базы, и опять же, я просто хотел бы услышать, какие опции доступны для достижения этого поведения.

Таким образом, функция вернет произвольный список. Этот список будет по крайней мере на нескольких уровнях глубиной.

mylist <- myfun(list(b = list(c = 3), foo = "bar"))

Пользователь должен иметь возможность доступа к сублиторам / элементам простым способом, аналогичным текущему доступу со знаком доллара

mylist$a$b$c
[1] 3

Это должно не иметь возможность редактировать этот объект.

mylist$a <- 5
Error:

Должно быть возможно удалить объект через

rm(mylist)
mylist
Error: object 'mylist' not found

Так что мой вопрос в том, чтоЕсть ли в R варианты для этого?

1 Ответ

2 голосов
/ 09 ноября 2019

Одним из способов достижения этого может быть создание нового класса (locked) вместе с методами для [<-, [[<- и $<- для этого нового класса, которые будут возвращать ошибку.

Например:

`[[<-.locked` <- function(...) {stop("Can't assign into locked object")}
a<-list(a="a",b=2)
a
  $a
  [1] "a"

  $b
  [1] 2

class(a)<-"locked"
a[[1]]<-"moose"
  Error in `[[<-.locked`(`*tmp*`, 1, value = "moose") : 
    Can't assign into locked object

a
  $a
  [1] "a"

  $b
  [1] 2

  attr(,"class")
  [1] "locked"

В этом случае все, что нужно вашей функции «только для чтения», это переопределить класс для объекта как locked:

class(out)<-c("locked",class(out))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...