Этот вопрос является своего рода продолжением этого сообщения так как я до сих пор не совсем уверен, что с точки зрения надежности кода было бы не намного лучше сделать привычку печатать namespace::foo()
вместо того, чтобы просто набирать foo()
и молиться, чтобы вы получили желаемый результат ;-)
Актуальный вопрос
Я знаю, что это сильно противоречит «стандартным соглашениям R», но скажем так, мне любопытно ;-) Можно ли каким-то образом прикрепить временное пространство имен к пути поиска?
Мотивация
В момент, когда мой пакет mypkg
все еще находится на «стадии разработки» (т.е. еще не настоящий пакет R):
- Я хочу передать свои функции в среду
mypkg
вместо.GlobalEnv
- затем присоедините
mypkg
к пути поиска (как истинное пространство имен, если возможно) - чтобы иметь возможность позвонить
mypkg::foo()
Я прекрасно понимаю, что вызов ::
имеет свои недостатки (он занимает больше времени, чем просто ввод имени функции и позволяет R неявно обрабатывать поиск) и / или может считаться необязательным из-за способа a) R просматривает путь поиска, и пакеты b) могут импортировать свои зависимости (т. Е. Использовать «Импорт» вместо «Зависит», не экспортируя определенные функции и т. Д.). Но я видел, как мой код вылетал как минимум дважды из-за того, что какой-то пакет перезаписывал определенные (базовые) функции, поэтому я перешел от «слепого доверия» к режиму «лучше быть безопасным, чем сожалеть»; -)
Что я пробовал
AFAIU, пространства имен в принципе не что иное, как некоторая особая среда
> search()
[1] ".GlobalEnv" "package:stats" "package:graphics"
[4] "package:grDevices" "package:utils" "package:datasets"
[7] "package:methods" "Autoloads" "package:base"
> asNamespace("base")
<environment: namespace:base>
И есть функция attach()
, которая прикрепляет объекты к пути поиска. Вот что я подумал:
temp.namespace <- new.env(parent=emptyenv())
attach(temp.namespace)
> asNamespace("temp.namespace")
Error in loadNamespace(name) :
there is no package called 'temp.namespace'
Полагаю, мне нужно как-то поработать с attachNamepace()
и выяснить, чего он ожидает, прежде чем он будет вызван в library()
. Любые идеи?
РЕДАКТИРОВАТЬ
Что касается комментария Хэдли: на самом деле мне было бы все равно, является ли присоединенная среда полноценным пространством имен или просто обычной средой, если я могу расширить ::
, сохранив функцию «синтаксического поиска» ( т.е. возможность звонить pkg::foo()
вместо "::"(pkg="pkg", name="foo")()
).
Так выглядит функция "::"
:
> get("::")
function (pkg, name)
{
pkg <- as.character(substitute(pkg))
name <- as.character(substitute(name))
getExportedValue(pkg, name)
}
Это то, что он также должен иметь возможность делать, если R обнаруживает, что pkg
на самом деле не пространство имен, а просто некоторая среда, прикрепленная к пути поиска:
"::*" <- function (pkg, name)
{
pkg <- as.character(substitute(pkg))
name <- as.character(substitute(name))
paths <- search()
if (!pkg %in% paths) stop(paste("Invalid namespace environment:", pkg))
pos <- which(paths == pkg)
if (length(pos) > 1) stop(paste("Multiple attached envirs:", pkg))
get(x=name, pos=pos)
}
Это работает, но нет синтаксического шугаринга:
> "::*"(pkg="tempspace", name="foo")
function(x, y) x + y
> "::*"(pkg="tempspace", name="foo")(x=1, y=2)
[1] 3
Как я смогу вызвать pkg::*foo(x=1, y=2)
(не считая того факта, что ::*
- действительно плохое имя для функции ;-))?
asNamespace
: Функции поддержки внутреннего пространства имен. Не предназначен для прямого вызова. - person James   schedule 25.03.2013devtools
делает более или менее то, что вы описываете. Вы можете прочитатьload_ALL()
, чтобы понять, как @hadley решил эту проблему. - person Andrie   schedule 25.03.2013mynamespace
(вместо.GlobalEnv
), чтобы иметь возможность вызыватьmynamespace::foo()
вместоfoo()
. Если бы мой код уже превратился в полноценный пакет, не было бы проблем. Но на этапе разработки я не могу использовать::
, так как настоящего пространства имен еще нет. Таким образом, вопрос, могу ли я создать временный. - person Rappster   schedule 26.03.2013devtools
- person Rappster   schedule 26.03.2013