Namespaces and name conflicts

421 篇文章 14 订阅

R packages ‘igraph’ and ‘network’ are good examples of two R packages providing similar but complementary functionalities for which there are a lot of name conflicts. As for now the ‘igraph’ package has a namespace while the ‘network’ package (version 1.4-1) does not. This became an issue when I was working on the ‘intergraph‘ package. Below is a note on how the fact that ‘igraph’ does and ‘network’ currently does not have a namespace affects using them simultaneously during an R session.

Loading and attaching ‘network’ and ‘igraph’ simultaneously (in this case ‘network’ first, ‘igraph’ second) gives

The following object(s) are masked from 'package:network':

add.edges, add.vertices, %c%, delete.edges, delete.vertices,
get.edge.attribute, get.edges, get.vertex.attribute, is.bipartite,
is.directed, list.edge.attributes, list.vertex.attributes,
set.edge.attribute, set.vertex.attribute

So let’s see how does it affect our work.

Attaching ‘network’ first, ‘igraph’ second

One of the conflicting functions is ‘add.edges’. When we call it from the console R starts looking for it in several places in a particular order. This can be inspected with ‘search’ function:

> search()
 [1] ".GlobalEnv"        "package:igraph"    "package:network"
 [4] "package:pnmath"    "package:stats"     "package:graphics"
 [7] "package:grDevices" "package:utils"     "package:datasets"
[10] "package:methods"   "Autoloads"         "package:base"

So R will look in global environment (aka Workspace) first and then in the code provided by the attached packages as shown. Consequently:

> # igraph version is on top
> args(add.edges)
function (graph, edges, ..., attr = list())
NULL
> # calling for version from network specifically
> args(network::add.edges)
function (x, tail, head, names.eval = NULL, vals.eval = NULL,
 ...)
NULL

Because ‘network’ does not have a namespace some of its functions are masked by the copies from ‘igraph’. A call to some function from ‘network’ that uses one of those conflicting functions will use the version from the ‘igraph’ package (so trigger an error most likely) and not the correct version from ‘network’. For example:

> x <- as.network(matrix(sample(0:1, 9, replace=TRUE), 3, 3))
Error in set.vertex.attribute(g, "na", rep(FALSE, n), 1:n) :
 Not a graph object

This tries to use ‘set.vertex.attribute’ from ‘igraph’ and not the correct one from ‘network’ because ‘igraph’ comes first on the search path as returned by ‘search()’.

Attaching ‘igraph’ first, ‘network’ second

First some clean-up then loading the packages

detach(package:network, unload=TRUE)
detach(package:igraph, unload=TRUE)

# igraph first
library(igraph)
library(network)

Now the network version of ‘add.edges’ is on top

> args(add.edges)
function (x, tail, head, names.eval = NULL, vals.eval = NULL,
 ...)
NULL

Version from ‘igraph’ can be called with ‘::’

> args(igraph::add.edges)
function (graph, edges, ..., attr = list())
NULL

Given that we attached ‘igraph’ first and ‘network’ second based on the previous section we could expect that this will brake the functioning of the ‘igraph’ package. Let’s see this with ‘V’ function in ‘igraph’ which calls ‘set.vertex.attribute’ (a name conflict with ‘network’).

> get("V<-")
function (x, value)
{
 if (!is.igraph(x)) {
 stop("Not a graph object")
 }
 if (!"name" %in% names(attributes(value)) || !"value" %in%
 names(attributes(value))) {
 stop("invalid indexing")
 }
 set.vertex.attribute(x, attr(value, "name"), index = value,
 value = attr(value, "value"))
}
<environment: namespace:igraph>

Let’s check that:

> g <- graph.full(3)
> V(g)$type <- 1:3

And this works OK because for packages with namespaces R uses a little different searching mechanism. It searches in package namespace first, then among the functions imported by that package, then R base, and lastly in the “normal” search path (as from ‘search()’). See “Writing R Extensions”, last paragraph before the end of sub-section. Consequently, the correct version of ‘set.vertex.attribute’ is used.

Both packages have namespaces

If both packages have namespaces the errors like the one with ‘as.network’ shown above cannot happen. The code provided in the packages will work correctly as they will use their own copies of conflicting functions. Using the namespaced ‘network’ I made while creating ‘intergraph‘:

> library(network, lib="~/lib/R/2.11-dev")
Loading ‘network’ from /home/mbojan/lib/R/2.11-dev/network
Classes for Relational Data
Version 1.4-1-1 created on 2008-11-17.
copyright (c) 2005, Carter T. Butts, University of California-Irvine
 Mark S. Handcock, University of Washington
 David R. Hunter, Penn State University
 Martina Morris, University of Washington
For citation information, type citation("network").
Type help("network-package") to get started.
Modified by MB
Loaded from “/home/mbojan/lib/R/2.11-dev”
> library(igraph)

Attaching package: 'igraph'

The following object(s) are masked from 'package:network':

 add.edges, add.vertices, %c%, delete.edges, delete.vertices,
 get.edge.attribute, get.edges, get.vertex.attribute, is.bipartite,
 is.directed, list.edge.attributes, list.vertex.attributes,
 set.edge.attribute, set.vertex.attribute

> net <- as.network(matrix(sample(0:1, 9, replace=TRUE), 3, 3))
> net
 Network attributes:
 vertices = 3
 directed = TRUE
 hyper = FALSE
 loops = FALSE
 multiple = FALSE
 bipartite = FALSE
 total edges= 2
 missing edges= 0
 non-missing edges= 2

 Vertex attribute names:
 vertex.names

 adjacency matrix:
 1 2 3
1 0 1 0
2 0 0 0
3 1 0 0

So, works OK even though we attached ‘network’ first and ‘igraph’ second.

Bottomline

  1. Name conflicts between R packages will be inevitable given the pace at which number of package on CRAN grow.
  2. Given that, using namespaces in packages is nowadays a necessity. See here how to do that.
  3. If one of the conflicting packages does not have a namespace it seems OK if you attach the namespaced package first and the non-namespaced one later.
  4. In case of name conflicts it is still the safest to use the :: operator and always specify what version (i.e. from which package) we want to use.

Filed under: networksR        

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值