Erlang maps:remove / 2和maps:without / 2之间的实际区别 [英] Practical difference between Erlang maps:remove/2 and maps:without/2

查看:145
本文介绍了Erlang maps:remove / 2和maps:without / 2之间的实际区别的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

检查
ErlangVM应该根据需要透明地在这些表示之间切换。



回答您的问题。如果要删除一个键-请使用 maps:remove / 2 ,如果要删除多个键,请使用 maps:without / 2 ,因为与使用旧地图相比,创建新地图可能更便宜。


Checking over the documentation for one of the new R17 features, maps, brought me to maps:remove/2 and maps:without/2. The only clear distinction I can see is that remove/2 takes a single key and returns a view of the map without it, where without/2 accepts a list and returns a completely new map lacking the listed keys.

22> M1 = #{foo => bar, spam => eggs}.
#{foo => bar,spam => eggs}
23> M2 = maps:without([foo], M1).
#{spam => eggs}
24> M3 = maps:remove(foo, M1).
#{spam => eggs}
25> M1.
#{foo => bar,spam => eggs}
26> M2.
#{spam => eggs}
27> M3.
#{spam => eggs}

What is the practical impact of this? I can appreciate not wanting to create in-memory copies of gigantic maps with without/2, but why doesn't remove/2 accept a list? I'm assuming there is a performance-oriented reason why these two functions exist the way they do, but I'm confused about when I would want to use one over the other in most situations (meaning, I don't think that maintaining gigantic maps are a generally good idea).

解决方案

The first thing about maps is that, the implementation may change. As Fred Hébert wrote in learn you some Erlang maps Chapter: "The OTP team is respecting the old slogan: first make it work, then make it beautiful, and only if you need to, make it fast." So don't depend on this answer too heavily.

Currently the maps:without/2 function is implemented like this:

without(Ks, M) when is_list(Ks), is_map(M) ->
    maps:from_list([{K,V}||{K,V} <- maps:to_list(M), not lists:member(K, Ks)]).

As you can see, it iterates over entire map. It converts it to list, removes the keys and converts it back to map. Not really efficient, but as I said: this may change in the future.

The maps:remove/2 function is a NIF, which means, it is written in C and takes advantage from internal representation. Speaking of which... During Stockholm Erlang Factory 2013 Kenneth Lundin mentioned maps internal representation (http://vimeo.com/69950294). Actually, there are two of them (sliedes are from the talk, that I linked to).

This one is for low amount of keys. In this representation, set of values has pointer to set of keys, which means, that if you change value, but not the key - keys will be shared. Also keys are sorted. Second one, for larger amounts of keys looks like this:

So it is a tree, which means, that if you for example delete a key on the right subtree, your new map could share entire left subtree. For more clear information on immutable data structures, you can refer to wikipedia ErlangVM should transparently switch between those representations as needed.

To answer your question. If you want to delete one key - use maps:remove/2, if you want to delete multiple keys, use maps:without/2, because it might be cheaper to create new map instead of manipulating the old one.

这篇关于Erlang maps:remove / 2和maps:without / 2之间的实际区别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆