Подтвердить что ты не робот

Динамическое создание ссылочных классов

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

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

Сначала я попытался создать новый класс с помощью простого:

myClass <- setRefClass("NewClassName", fields=list(fieldA="character"))

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

Затем я нашел поток, который предложил использовать что-то для эффекта:

myClass <- setRefClass("NewClassName", fields=list(fieldA="character"), where=globalenv())

Это фактически разбило R/Studio, когда я пытался создать пакет, поэтому у меня нет журнала ошибки, сгенерированной, к сожалению, но это, безусловно, не сработало.

Далее я попытался создать новую среду в моем пакете, которую я мог бы использовать для хранения этих ссылочных классов. Поэтому я добавил строку .classEnv <- new.env() в своих источниках пакетов (не внутри какой-либо функции), а затем попытался использовать этот класс при создании нового ссылочного класса:

myClass <- setRefClass("NewClassName", fields=list(fieldA="character"), where=.classEnv) 

Это действительно работало нормально, но генерирует следующее предупреждение:

> myClass <- setRefClass("NewClassName", where=.classEnv)
Warning message:
In getPackageName(where) :
  Created a package name, ‘2013-04-23 10:19:14’, when none found

Итак, по какой-то причине methods::getPackageName() не может выбрать, в каком пакете находится моя новая среда?

Есть ли способ создать новую среду по-другому, чтобы getPackageName() мог правильно распознать пакет? Могу ли я добавить некоторую функцию, которая позволяет мне помочь getPackageName() обнаружить пакет? Будет ли это работать, если я смогу справиться с предупреждением, или я злоупотребляю ссылочными классами, пытаясь создать их динамически?

4b9b3361

Ответ 1

Чтобы начать разговор, я обнаружил, что getpackageName хранит имя пакета в скрытой переменной .packageName в указанной среде.

Итак, вы можете обойти предупреждение с помощью

assign(".packageName", "MyPkg", envir=.classEnv)    
myClass <- setRefClass("NewClassName", fields=classFields, where=.classEnv)

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

Подробная информация из документации:

Имена пакетов обычно устанавливаются во время загрузки пакета, установкой INSTALL script или библиотечной функцией. (В настоящее время имя сохраняется как объект .packageName, но не доверяет этому в будущем.)


Edit

После прочтения немного далее метод setPackageName может быть более надежным способом установки имени пакета для среды. В документах:

setPackageName может использоваться для установки имени пакета в среде, которая иначе не имела бы этого. Это позволяет создавать классы и/или методы в произвольной среде, но обычно предпочтительнее создавать пакеты с помощью стандартных инструментов программирования R (package.skeleton и т.д.).

Итак, похоже, что одно действительное решение будет следующим:

setPackageName("MyPkg", .classEnv)
myClass <- setRefClass("NewClassName", fields=classFields, where=.classEnv)

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