文档结构  
翻译进度:已翻译     翻译赏金:0 元 (?)    ¥ 我要打赏

今天的Erlang Thursday我们开始看 digraph 模块。

当我研究这个模块的时候,发现这个模块并不和我预料的Erlang行为一样,所以我想在研究它的函数前仔细看看它那些与众不同的地方。

如果我们查看所有digraph模块的函数,我们只能找到两个函数 digraph:new/0 和 digraph:new/1 返回 digraph 类型数据。

我想看看这个Erlang API有什么奇怪的,我打开Erlang shell,添加一个节点到有向图然后检查这个操作的结果。

第 1 段(可获 1.26 积分)
G = digraph:new().
% {digraph,69651,73748,77845,true}
G2 = digraph:add_vertex(G, foo, bar).
% foo
调用 digraph:add_vertex/3 返回的结果是foo,也就是传给它的第二个入参,这个结果并不像一个有向图的样子。

那么,再回过头来看看变量G是否有变化。

G.
% {digraph,69651,73748,77845,true}
元组形式的结果看起来和原来一样,那么我们看看那个节点是否在图里,因为我们获得返回值是foo。
digraph:vertices(G).
% [foo]
digraph:vertex(G, foo).
% {foo,bar}

 

第 2 段(可获 0.85 积分)

看来那个节点的确在图中。

让我们再加入另一个节点到与变量G绑定到图中。

V = digraph:add_vertex(G).
% ['$v'|0]
digraph:vertices(G).
% [['$v'|0],foo]

这个节点也添加成功。

困惑所在

所以在研究这个模块的函数之前在本文中我要重点讲出来的这个行为模式是这些函数在图中显而易见地展现了可修改的行为模式。

我说它是显而易见的可修改的,因为如果它在底层的实现上是不可修改的,结构可以改变同时绑定的变量的引用保持不变。

第 3 段(可获 1.23 积分)
digraph:vertices(G).
% [['$v'|0],foo]
Copy = G.
% {digraph,69651,73748,77845,true}
V2 = digraph:add_vertex(G, wat).
% wat
digraph:vertices(Copy).
% [['$v'|0],foo,wat]
digraph:vertices(G).
% [['$v'|0],foo,wat]

甚至其他变量引用也改变,所以它颠覆了我见过的在Erlang生态圈里关于所有数据是不可变的任何常规。

我们将在后续的Erlang Thursday文章中研究digraph模块的函数,但是我想花点时间讲这个模块中的可变性的内在本质,所以当你需要使用这个模块的时候,你一定要认识到如果不谨慎的话你想在你的应用的并发部分使用它将很危险。

第 4 段(可获 1.06 积分)

修改 (10月18日)

做为 LFE Fridaystranslation into Lisp Flavored Erlang 的一部分,Robert Virding 告诉我这个模块的可变性的原因,这个内容也包含在他翻译本文的文章里。

屠龙(解惑)

这背后的原因是这个模块是如何实现的。一个 有向图 底层的实现上有三个 ETS 表。在上述例子里,这些表的id是 8207,12304和16401。你可以调用 ets:i/0 来看到,这个函数列出所有当前ets表。你可以看到那3个表属于Erlang shell进程。

> self().
<0.28.0>
> ets:i().
 id              name              type  size   mem      owner
 ----------------------------------------------------------------------------
 1               code              set   282    10393    code_server
 4098            code_names        set   64     7713     code_server
 8207            vertices          set   3      328      <0.28.0>
 12304           edges             set   0      305      <0.28.0>
 16401           neighbours        bag   2      319      <0.28.0>
 ac_tab          ac_tab            set   6      839      application_controller
 file_io_servers file_io_servers   set   0      305      file_server_2
 global_locks    global_locks      set   0      305      global_name_server
 global_names    global_names      set   0      305      global_name_server
...

ok

 

第 5 段(可获 1.19 积分)

有向图它自己的结构仅是一个标签元组,包含着ets表id。所有的改变都发上在ETS表里,图的结构本身从未改变。表的数据和内容可以用 ets:info/1ets:i/1 来读取。

第 6 段(可获 0.54 积分)

文章评论