使用ets:foldl作为每个记录的穷人forEach

简短版本:使用
ets:foldl
删除每个ETS记录是否安全,因为正在迭代它们? 假设一个ETS表正在累积信息,现在是时候处理它了。从表中读取记录,以某种方式使用,然后删除。 (另外,假设该表是
private
,因此没有并发问题。) 在另一种语言中,使用类似的数据结构,您可以使用for ... each循环,处理每个记录,然后从hash / dict / map /中删除它。但是,
ets
模块没有
foreach
,例如
lists
。 但这可能有效:
1> ets:new(ex, [named_table]).
ex
2> ets:insert(ex, {alice, "high"}).
true
3> ets:insert(ex, {bob, "medium"}).
true
4> ets:insert(ex, {charlie, "low"}).
true
5> ets:foldl(fun({Name, Adjective}, DontCare) ->
      io:format("~p has a ~p opinion of you~n", [Name, Adjective]),
      ets:delete(ex, Name),
      DontCare
   end, notused, ex).
bob has a "medium" opinion of you
alice has a "high" opinion of you
charlie has a "low" opinion of you
notused
6> ets:info(ex).
[...
 {size,0},
 ...]
7> ets:lookup(ex, bob).
[]
这是首选方法吗?它至少是正确的,没有错误吗? 我对在处理数据结构时修改数据结构有一个普遍的关注,但是ets:foldl文档暗示ETS非常适合修改
foldl
中的记录。由于我基本上擦桌子干净,我想确定。 我正在使用Erlang R14B和
set
表但是我想知道是否有任何Erlang版本或任何类型的表格的警告。谢谢!     
已邀请:
你的方法很安全。安全的原因是
ets:foldl/3
内部使用
ets:first/1, ets:next/2
ets:safe_fixtable/2
。这些都有你想要的保证,即你可以杀死元素并仍然获得完整的遍历。请参阅
erl -man ets
的CONCURRENCY部分。 为了从表中删除所有元素,有一个更简单的单行:
ets:match_delete(ex, '_').
虽然它不起作用你应该为每一行做IO格式化,在这种情况下你的方法可能更容易。     
对于这样的情况,我们将在两个表之间交替,或者每次开始处理时创建一个新表。当我们想要开始一个处理周期时,我们将编写器切换为开始使用备用表或新表,然后我们进行处理并清除或删除旧表。 我们这样做是因为可能会有一个我们可能错过的元组的并发更新。当我们使用这种技术时,我们正在使用高频并发计数器。     

要回复问题请先登录注册