gpt4 book ai didi

erlang - 如何在erlang中创建一个非常大的列表

转载 作者:行者123 更新时间:2023-12-02 06:54:16 24 4
gpt4 key购买 nike

我们使用lists:seq(1,100)创建一个包含100个元素的列表,创建速度还可以

但是如果我们创建一个包含 1000w 元素的列表怎么办?lists:seq(1,10000000) 非常慢。

您是否有想法在没有任何数据复制的情况下创建一个大型列表?

最佳答案

实际上,lists:seq/2不执行任何复制。下面是实际的实现:

seq(First, Last)
when is_integer(First), is_integer(Last), First-1 =< Last ->
seq_loop(Last-First+1, Last, []).

seq_loop(N, X, L) when N >= 4 ->
seq_loop(N-4, X-4, [X-3,X-2,X-1,X|L]);
seq_loop(N, X, L) when N >= 2 ->
seq_loop(N-2, X-2, [X-1,X|L]);
seq_loop(1, X, L) ->
[X|L];
seq_loop(0, _, L) ->
L.

因此,它递归地调用自身,在每次调用中将最多 4 个元素添加到累加器(第三个参数)。将元素添加到列表中不涉及任何复制,并且调用是尾递归的,因此堆栈具有恒定的大小。

编辑:为了完整起见,我粘贴了评论中的一些澄清:Erlang 列表是链接列表。在内部 [H|T],创建元素 H 并添加指向 T 的指针。T 永远不会被复制。你可以这样做,因为 T 是不可变的,它永远不会改变,即使你创建 [H1 | T],[H2 | T] 和 [H3 | T] - T 在他们之间共享。

使用列表作为参数调用函数也不涉及复制:)包括列表在内的更大的数据结构存储在进程堆上。您只存储指向堆栈上第一个元素的指针。只有发送消息到另一个进程才会真正复制列表。

创建非常大的列表可能会很慢,因为您可能会耗尽物理内存并开始使用交换。编辑结束

关于迭代,我想以 Nicolas Talfer 的答案为基础 - 有时你想将参数传递给循环中调用的函数,你可以使用高阶函数和闭包来做到这一点:

main(_) ->
InitialArgs = 6,
InitialFun = fun() -> do_stuff(InitialArgs) end,
Ret = forloop(InitialFun, 5),
io:format("~p", [Ret]).

forloop(Fun, 1) ->
Fun();
forloop(Fun, Count) ->
RetVal = Fun(),
NewFun = fun() -> do_stuff(RetVal) end,
forloop(NewFun, Count-1).

do_stuff(Args) ->
Args + 2.

关于erlang - 如何在erlang中创建一个非常大的列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25782973/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com