遍历和更新Erlang ETS表中的所有元素的最佳方法是什么?

遍历和更新Erlang ETS表中的所有元素的最佳方法是什么?,erlang,updates,traversal,ets,Erlang,Updates,Traversal,Ets,你能帮我一个“最佳实践”方法吗?在更新每个元素时,只对ETS表中的所有元素迭代一次?我的表是一个私有集,我准备使用输入函数中的ets:foldl遍历它,但我不确定这是否是一种安全的方法,因为根据文档,破坏性地更新元素可能会在另一次给我相同的元素。我不打算插入新的密钥,只更新值,请告诉我,如果这种方法是安全的,或告诉我一种替代方法,以实现高效的更新 谢谢大家! 您可以使用first/1和next/2。请参见此处的next/2doco: 我认为ets文档已经回答了您的问题: ETS内没有其他支持可以

你能帮我一个“最佳实践”方法吗?在更新每个元素时,只对ETS表中的所有元素迭代一次?我的表是一个私有集,我准备使用输入函数中的
ets:foldl
遍历它,但我不确定这是否是一种安全的方法,因为根据文档,破坏性地更新元素可能会在另一次给我相同的元素。我不打算插入新的密钥,只更新值,请告诉我,如果这种方法是安全的,或告诉我一种替代方法,以实现高效的更新


谢谢大家!

您可以使用
first/1
next/2
。请参见此处的
next/2
doco:

我认为
ets
文档已经回答了您的问题:

ETS内没有其他支持可以保证 对象之间的一致性。但是,safe_fixtable/2功能可以 用于确保第一次/1和下一次/2调用序列 无错误地遍历表,并确保 表只被访问一次,即使是另一个进程(或相同的进程) 处理)同时将对象删除或插入到表中。 再也不能保证了;特别是插入或删除的特定对象 在这样的遍历过程中删除的内容可以访问一次,也可以根本不访问。 内部遍历表的函数,如select和 匹配,将提供与安全固定相同的保证


以下是我的结论,也许有人会发现它很有用:

%% @doc
%% Traverses each element in an ETS table, and calls Fun on them.
%% Use with caution, when inserting or deleting elements, see the
%% ETS documentation for details!
-spec ets_each(
    TableRef :: ets:tid( ),
    Fun      :: fun( ( Key :: term( ), [ Element :: term( ) ], Extra :: term( ) ) -> ok ),
    Extra    :: term( )
) ->
    ok.
ets_each( TableRef, Fun, Extra ) ->
    ets:safe_fixtable( TableRef, true ),
    First = ets:first( TableRef ),
    try
        do_ets_each( TableRef, Fun, Extra, First )
    after
        ets:safe_fixtable( TableRef, false )
    end.

%% @doc
%% Recursive helper function for ets_each.
-spec do_ets_each(
    TableRef :: ets:tid( ),
    Fun      :: fun( ( Key :: term( ), [ Element :: term( ) ], Extra :: term( ) ) -> ok ),
    Extra    :: term( ),
    Key      :: term( )
) ->
    ok.
do_ets_each( _TableRef, _Fun, _Extra, '$end_of_table' ) ->
    ok;    
do_ets_each( TableRef, Fun, Extra, Key ) ->
    Fun( Key, ets:lookup( TableRef, Key ), Extra ),
    do_ets_each( TableRef, Fun, Extra, ets:next( TableRef, Key ) ).

谢谢你的回答,安东尼!挖掘ets.erl的源代码后,发现
foldl/3
使用了相同的方法(使用
safe\u fixtable/2
固定表,从
first/1
开始,递归调用
next/2
),因此它将确保每个元素只到达一次,但对于我的场景,我也可以这样做,没有累加器的开销,因为我不需要它们。只需几行加上,以减少计算时间。:)