Function set_edge_attr does not seem to work

The following code

library(igraph)
g1 <- make_ring(3) %>% set_edge_attr("weight", value = seq(3) )
edge_attr(g1)

gives as expected

$weight
[1] 1 2 3

However, similar code:

g2 <- make_ring(3)
set_edge_attr(g2, "weight", value = seq(3) )
edge_attr(g2)

gives
list()

I would expect the same output. Any thoughts why this isn’t the case?

set_edge_attr does not mutate an existing graph. It returns a new graph with modified attributes.

Thanks. I missed that.

In my opinion the documentation is too cryptic.
In stead of

Set edge attributes

it should be something like:

set_edge_attr creates a new graph, updating the edge attributes.

This is not specific to set_edge_attr but a fundamental principle of R. Like typical functional languages, R uses call-by-value, and functions cannot modify their arguments. All other functions will return modified values as well, instead of modifying variables passed to them.

To close this topic:

g$main <- "This is bad practice"

However:

g <- set_graph_attr(g, name="main", value="This is functional programming good practice")

First, I have to say that I rarely use R and can’t really say what is / isn’t considered good practice … My involvement with igraph is mainly through its C core and Mathematica interface.

However, I would not say that g$main <- "This is bad practice". I don’t think there’s anything wrong with that.

My point was that it is not possible to write an R function that changes a variable. The following is not possible:

x <- 1
f(x)
# now the value of x is 2

Only this is possible:

f <- function(a) { a + 1 }
x <- 1
x <- f(x)

This is because conceptually, R works with values, not with references. Some other languages, like Python, work with references, and you can do this:

In [1]: a=[1,2,3]

In [2]: b=a

In [3]: b[1]=100

In [4]: a
Out[4]: [1, 100, 3]

Notice that modifying b modified a as well. More accurately, a and b refer to the same data structure. In R each variable name is associated with an independent value. Modifying one variable will never affect another. Thus modifying a (local) function argument won’t change the (global) variable that was passed to the function.

All that said, generally speaking, improvements to the documentation are very welcome. Feel free to open pull requests with doc improvements. The R/igraph docs certainly need an update.

The argument is that the statement

`g$main <- "This is bad practice"`

is based on the internal structure of the graph g. In the (unlikely) case that it is decided to move $main to another position, the code will fail.

In contrast, retrieving data by functions get*attr is independent of the internal representation of g and is therefore more robust.

I admit this is a rather purist approach.