2015-12-18 3 views
0

Я пытаюсь создать список конфликтов пространства имен между пакетами в R, но функция conflicts() имеет какое-то странное поведение, например, с помощью функции p в пакетах shiny и htmltools (который shiny импорт):Почему R сообщает конфликт пространства имен для идентичных функций?

> require(shiny) 
> ## print source from shiny namespace... 
> shiny::p 
function (...) 
tags$p(...) 
<environment: namespace:htmltools> 
> require(htmltools) 
> ## print source from htmltools namespace... 
> htmltools::p 
function (...) 
tags$p(...) 
<environment: namespace:htmltools> 

Таким образом, источник для p точно такой же и даже из одного и того же пространства имен для обоих этих пакетов (файлы справки также идентичны), но если вы запустите conflicts(detail = TRUE), эта функция отображается как конфликт между двумя пакетами , Почему это указано как конфликт, и есть ли способ обнаружить «конфликты» этого типа? Связано ли это с тем фактом, что вы можете напрямую вызвать функцию либо из пространства имен shiny, либо из htmltools?

+0

Связанных: http://stackoverflow.com/ q/30626904/2679518 –

ответ

1

Функция conflicts просто проверяет имена, которые содержатся в нескольких пакетах на вашем пути поиска. Он не проверяет, являются ли фактические объекты, обозначенные этими именами, одинаковыми или нет.

Вы можете посмотреть названия объектов в пространстве имен пакета, используя objects() (который также используется внутри conflicts()) или ls(). Например:

head(objects("package:shiny"), 10) 
## [1] "a"    "absolutePanel" "actionButton"  "actionLink"  "addResourcePath" 
## [6] "animationOptions" "as.shiny.appobj" "basicPage"  "bootstrapPage" "br" 

Если запустить

which(objects("package:shiny") == "p") 
which(objects("package:htmltools") == "p") 

вы увидите пространство имен из shiny и htmltools оба содержат объект по имени p. conflicts просто проверяет все имена, которые появляются в более чем одном пространстве имен в search() и p является одним из них, если у вас есть shiny и htmltools прилагается.

Чтобы выяснить, почему shiny содержит функцию, которая acutally в пространстве имен htmltools, вы можете посмотреть на NAMESPACE файл в источнике shiny. Он содержит следующие строки

export(p) 
import(htmltools) 

export делает функцию видимую для тех, кто использует пакет. Таким образом, это экспортированных функций, которые вы можете позвонить после того, как вы установили пакет с library(). import(htmltools) гарантирует, что все Экспортируемые объекты в htmltools могут быть использованы в shiny. Однако он не делает функции от htmltools доступным для тех, кто работает library(shiny).

Поскольку shinyимпорта все функции из htmltools (включая p()), а затем также экспортp(), p() (от htmltools) видна после library(shiny).

Вы можете проверить, действительно ли два конфликтующих объекта одинаковы, используя identical().Это покажет вам, что функция p() в shiny и htmltools тот же:

library(shiny) 
library(htmltools) 
identical(htmltools::p, shiny::p) 
## [1] TRUE 

С другой стороны, dplyr определяет функцию filter(), которая отличается от той, в stats:

library(dplyr) 
identical(dplyr::filter, stats::filter) 
## [1] FALSE 

Наконец , позвольте мне предложить способ проверить, является ли какой-то конфликт (то есть имя, которое появляется в нескольких прикрепленных пакетах) «настоящим» конфликтом. Под «реальным» я имею в виду, что объекты, которые имеют имя, являются , а не. Итак, filter() в приведенном выше примере будет «реальным» конфликтом, а «p» - нет. Следующая функция возвращает TRUE для «реального» конфликта и ложь в противном случае:

is_real_conflict <- function(conf_obj) { 

    # get list of all conflicts 
    conf_all <- conflicts(detail = TRUE) 
    # get names of packages that contain an object with name conf_obj 
    conf_pck <- names(conf_all)[sapply(conf_all, function(pck) conf_obj %in% pck)] 
    # get the actual objects associated with these names 
    objs <- lapply(conf_pck, function(ns) get(conf_obj, envir = as.environment(ns))) 
    # compare each of the objects to the first one 
    comp <- sapply(objs, identical, objs[[1]]) 
    # the following returns FALSE only if all the objects are the same 
    return (!all(comp)) 
} 

Вы можете проверить все конфликтующие имена на одном дыхании с помощью

sapply(conflicts(), is_real_conflict) 
+0

Очень четкий и тщательный ответ! В качестве дополнительной информации для будущих читателей кажется, что 'same()' будет возвращать 'FALSE', даже если разности функций синтаксически бессмысленны. Например, если вы определяете 'F <- функция (x) return (x); G <- функция (y) return (y); Z <- function (x) return (x) ', ' same (F, G) 'и' same (F, Z) 'оба возвращают' FALSE'. –

+0

Да, это правда. 'same()' не проверяет, дают ли две функции одинаковый результат для идентичных входов. – Stibu

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