我的问题是,如何在Erlang中实现数组,而不是列表。
使用不可变类型执行类似的操作
move ([X | Xs], Ys) ->
[X | Ys].
Ls = move([1,2,3], [2,3,4])
将占用堆中的常量mem,因为这是所有参考工作。
但对于数组中的相同内容
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成比例的大小,还是能够像数组那样在恒定的空间内执行此操作?
答案 0 :(得分:7)
(希望)清楚一点。请记住,在Erlang ALL 数据是不可变的!这极大地影响了您操纵数据的方式。
array
模块构建嵌套元组的结构,其中包含数据的所有数组槽位于同一级别。每个元组的大小为10,因此对于数组访问,我们有O(lg10(N))。使用这样的嵌套结构在具有不可变数据的语言中很常见。你可以将数组保存在一个扁平元组中,这样可以快速读取,但写入会变得很慢并且内存占用大数组/元组,因为每次写入都需要创建一个新的元组。使用树结构意味着在写入中创建的数据要少得多。
move/2
函数如何影响内存使用量取决于您是否要写入数组中已使用或未使用的插槽。如果插槽已在使用中,则结果内存使用情况将相同。如果您正在写入以前未使用的插槽,那么您可能需要增加数组,这意味着将使用更多内存。
这与您的列表案例完全相同。
还取决于是否存在对旧数据结构的任何剩余引用。
答案 1 :(得分:2)
您可以找到源代码here。看起来像@rvirding提到的那样,数组是一个功能树。我没有深入研究实现 - 并且源代码中没有引用数据结构的起源 - 但快速浏览表明查找最坏情况是N的对数因子。
如果其他人更熟悉这个来源/我有时间研究它,我会喜欢纠正。