4

我的问题是,数组是如何在 Erlang 中实现的,而不是列表。

使用不可变类型做类似的事情,

move ([X | Xs], Ys) ->
    [X | Ys].

Ls = move([1,2,3], [2,3,4])

将占用堆中的常量内存,因为这都是参考工作。

但是对于数组中的相同内容

move (A1, A2) ->
    array:set(0, array:get(0,A1),A2).

A1 = array:from_list([1,2,3]).
A2 = array:from_list([0,2,3,4]).
A3 = move(A1,A2).

这里会move使用与 A2 成比例的大小,还是能够像数组一样在恒定空间中执行此操作?

4

2 回答 2

9

(希望)把事情弄清楚一点。请记住,在 Erlang 中,所有数据都是不可变的!这会深刻影响您处理数据的方式。

array模块构建了一个嵌套元组的结构,其中包含数据的所有数组槽都处于同一级别。每个元组的大小为 10,因此对于数组访问,我们有 O(lg10(N))。像这样使用嵌套结构在具有不可变数据的语言中很常见。您可以将数组保存在一个平面元组中,这样可以快速读取,但是写入会变得很慢并且对于大型数组/元组会占用内存,因为每次写入都需要创建一个新元组。使用树结构意味着在写入中创建的数据要少得多。

您的move/2函数如何影响内存使用在一定程度上取决于您是写入数组中已使用的插槽还是未使用的插槽。如果插槽已在使用中,则生成的内存使用量将相同。如果您正在写入以前未使用的插槽,那么您可能需要增加数组,这意味着将使用更多内存。

这与您的列表案例完全相同。

它还取决于是否还有对旧数据结构的任何剩余引用。

于 2013-05-09T14:34:45.243 回答
2

您可以在此处找到源代码。正如@rvirding 所提到的,看起来数组是一棵功能树。我还没有深入研究过实现——而且源代码中没有提到数据结构的来源——但快速浏览表明查找最坏情况是 N 的某个对数因子。

如果其他人更熟悉这个来源/有时间研究它,我会喜欢更正。

于 2013-05-08T20:42:43.973 回答