由于其副作用,将图表保存到mnesia受到阻碍

时间:2013-09-24 18:47:42

标签: erlang

更新

erlang中的digraph库实现了一个副作用的数据类型。对数据类型的每个操作都将其新状态保存在ets表中 - 而不是返回自身的更改版本,这在函数式语言中更为常见。

从使用角度来看,问题在于它阻碍了我通过要求我先收集"收集"在我开始玩它之前的状态。

到目前为止,我见过的最接近的解决方案是serializer/deserializer,但这些解决方案的缺点是它们与有向图的当前结构相关联,而不是在抽象类型上运行 - 这阻止了未来的证明解决方案。

更新

帕斯卡指出了另一个利用有向图界面的串行器,因此消除了上述缺点。它显然好多了,虽然仍然不方便,但我认为没有更好的选择。


您对如何存储有向图的建议是什么?我应该完全使用不同的数据类型吗?

感谢。

2 个答案:

答案 0 :(得分:1)

我不确定你理解你的担忧。有效图存储在ETS中的事实在用户界面中是透明的,因此您可能希望将其换成与另一个进程交换有向图,制作副本或在发生崩溃时拥有永久存储。

对于前两个主题,可以很容易地在元组{Cyclic,Protect,[Vertice],[edge]}中检索有向图的定义然后进行交换:

digraph_To_Tuple(Di) ->
    Opt = digraph:info(Di),
    Vs = [digraph:vertex(Di,X) || X <- digraph:vertices(Di)],
    Es = [digraph:edge(Di,X) || X <- digraph:edges(Di)],
    {proplists:get_value(cyclicity,Opt),proplists:get_value(protection,Opt),Vs,Es}.

clone (Di) -> 
    {Cyclic,Protect,Vs,Es} = digraph_To_Tuple(Di),                                                                        
    Do = digraph:new([Cyclic,Protect]),                                                                            
    [digraph:add_vertex(Do,V,N) || {V,N} <- Vs ],  
    [digraph:add_edge(Do,E,S,D,N) || {E,S,D,N} <- Es], 
    Do.

最后一个主题是一个真正的问题,因为一旦创建它的进程死亡,ets就会被销毁。有一些方法可以将所有权赠予其他进程,但在这种情况下,ets实现的独立性将丢失。更好的可能性是在一个过程中创建有向图并将其传递给其他负责的过程来操纵它们。

但是,如果不重新编写部分或整个模块,我认为没有任何意义可以拥有其他类型的存储。

答案 1 :(得分:1)

您还可以使用Erlang的sofs(集合集)模块来获取完整的不可变数据结构,其中包含之后重建相同图形所需的所有数据

clone(Digraph) ->
  Family = sofs:digraph_to_family(Digraph),
  sofs:family_to_digraph(Family).