2013-04-23 9 views
13

Я пытаюсь генерировать ссылочные классы в 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() обнаружить пакет? Будет ли это работать, если я смогу справиться с предупреждением, или я злоупотребляю ссылочными классами, пытаясь создать их динамически?

+0

'? SetRefClass' говорит, что аргументы' ... 'передаются'? SetClass', и у этого есть аргумент 'package'; вы хотите принять свой третий подход, с аргументом 'package = 'YourPackage'' или что-то еще? –

+0

Спасибо за отзыв, Мартин. К сожалению, эта ошибка не была удалена. Похоже, что имя пакета не просачивается полностью до 'getPackageName', откуда появляется предупреждение, если переменная' .packageName' еще не указана. –

ответ

5

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

Таким образом, вы можете на самом деле обойти предупреждение с

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

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

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

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


Edit:

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

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

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

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

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

Смежные вопросы