当我们谈论Erlang Maps时,我们谈论什么 Part 2
声明:本文讨论的Erlang Maps是基于17.0-rc2,时间2014-3-4.兴许Maps可能会出现语法或函数API上的有所调整,特此说明.
前情提要: [Erlang 0116] 当我们谈论Erlang Maps时,我们谈论什么 Part 1
继续昨天的话题,在Erlang Factory SF Bay Area 2013有一个议题:"Where are we on the Map?" [PDF ],这个Talk基本上就是选取了EEP43的要点,有兴趣的同学能够FQ观看视频 Where are We on the Map?
- Kenneth Lundin - YouTube 假设是腿脚不利索的,能够看墙内的.细致阅读EEP43,其信息量巨大,包括Maps的设计演变来龙去脉,各种取舍,也是我们学习设计的极佳范例.以下我将依照自己的逻辑顺序又一次解读EEP43,先从怎样使用開始,直观上感受一下区别,然后再回答"何必有我"的问题.
Maps Basic
EEP43 给出了Map比較规范的定义, Map M包括一定数量的键值对,实现从K1..Kn到V1..Vn的映射,当中没有两个Key是相等的(equal). equal指的是K1==K2,matching指的是K1 =:= K2. erlang:is_map(M)用于推断数据是否map类型.只是依照如今的情况,当出现1.0和1做key的时候,结果和EEP43中设计的结果不同,还是要看下一个版本号是怎么处理的,这个不小心就是个坑:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
Eshell V6.0 (abort with ^G) 1> M=#{1=>a}. %% Construction syntax #{1 => a} 2> M#{1.0 => b}. #{1 => a,1.0 => b} 3> M#{1 => b}. #{1 => b} 4> M#{1 := b}. #{1 => b} 5> M#{1.0 := b}. ** exception error: bad argument in function maps:update/3 called as maps:update(1.0,b,#{1 => a}) in call from erl_eval: '-expr/5-fun-0-' /2 (erl_eval.erl, line 249) in call from lists:foldl/3 (lists.erl, line 1261) 6> M2= #{1=>a,1=>b,1.0 =>c}. #{1 => b,1.0 => c} 7> 1 == 1.0. true 8> #{1.0 =>a ,1 =>b}. #{1 => b,1.0 => a} |
构造Map的时候我们重点要验证的就是"Maps in Erlang are ordered, Important!!!! – Maps with the same set of keys are always presented in the same way":
1
2
3
4
5
6
7
8
9
|
Eshell V6.0 (abort with ^G) 1> #{a=>124,b=>1024,c=>23}. #{a => 124,b => 1024,c => 23} 2> #{b=>1024,c=>23,a=>124}. #{a => 124,b => 1024,c => 23} 3> #{b=>1024,a=>124,c=>23}. #{a => 124,b => 1024,c => 23} 4> M=#{b=>1024,a=>124,c=>23}. #{a => 124,b => 1024,c => 23} |
看下Map的基本操作,构造,更新,模式匹配.注意以下代码中 #{f:=F,a:={A,B}} = M.做匹配的时候,前面的部分key是顺序无关的.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
Eshell V6.0 (abort with ^G) 1> M=#{a=>{1,2},b=>23,<< "OK" >> =>ok, f=>fun()->receive a -> "Got a!" end end}. #{a => {1,2},b => 23,f => #Fun<erl_eval.20.101568567>,<<"OK">> => ok} 2> M#{b=>1024}. #{a => {1,2},b => 1024,f => #Fun<erl_eval.20.101568567>,<<"OK">> => ok} 3> M#{b2=>1023}. #{a => {1,2},b => 23,b2 => 1023,f => #Fun<erl_eval.20.101568567>,<<"OK">> => ok} 4> M#{b2 :=1024}. ** exception error: bad argument in function maps:update/3 called as maps:update(b2,1024, #{a => {1,2},b => 23,f => #Fun<erl_eval.20.101568567>,<<"OK">> => ok}) in call from erl_eval: '-expr/5-fun-0-' /2 (erl_eval.erl, line 249) in call from lists:foldl/3 (lists.erl, line 1261) 5> M#{b :=1024}. #{a => {1,2},b => 1024,f => #Fun<erl_eval.20.101568567>,<<"OK">> => ok} 6> #{f:=F,a:={A,B}} = M. #{a => {1,2},b => 23,f => #Fun<erl_eval.20.101568567>,<<"OK">> => ok} 7> b(). A = 1 B = 2 F = fun() -> receive a -> "Got a!" end end M = #{a => {1,2},b => 23,f => #Fun<erl_eval.20.101568567>,<< "OK" >> => ok} ok 8> 2> M=#{a=>123,b=>234}. #{a => 123,b => 234} 3> M#{a=>1000}. #{a => 1000,b => 234} 4> M#{not_key=>1000}. #{a => 123,b => 234,not_key => 1000} 5> M#{a :=1024}. #{a => 1024,b => 234} 6> M#{not_key :=1024}. ** exception error: bad argument in function maps:update/3 called as maps:update(not_key,1024,#{a => 123,b => 234}) in call from erl_eval: '-expr/5-fun-0-' /2 (erl_eval.erl, line 249) in call from lists:foldl/3 (lists.erl, line 1261) 7> P=#{name=> "zen" ,id=>2002}. #{id => 2002,name => "zen"} 8> P#{naem=>1024}. #{id => 2002,naem => 1024,name => "zen"} |
上面更新字段名称的方式,是用=> 还是:= ?从project层面考虑,我会选择 := 运算,由于当给一个不存在的key进行赋值的时候,会抛出错误bad argument.而上面第7~8行代码,本意是更新name字段,可是由于拼写错误原来的字段值没有改动,仅仅添加了一错误字段.在project代码中显然:=会大大减少排错的成本.
然后就是经常使用的 Function Header Match,这里能够看到新增了两个Guard erlang:is_map erlang:map_size
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
-module(a). -compile(export_all). test(#{state := {ok,State}} =S) -> State. Eshell V6.0 (abort with ^G) 1> a:test(). ** exception error: undefined function a:test/0 2> a:test(#{state => {ok,200}}). 200 3> a:test(#{state => {error,200}}). ** exception error: no function clause matching a:test(#{state => {error,200}}) (a.erl, line 7) 4> -module(a). -compile(export_all). a(#{state := {ok,State}} = S) when erlang:is_map(S) -> State. b(#{state := {ok,State}} = S) when erlang:map_size(S) >=1 -> State. test(#{state := {ok,State}} =S) when erlang:is_map(S) andalso erlang:map_size(S) >=1 -> State. Eshell V6.0 (abort with ^G) 1> a:b(#{state => {ok,200},id=>123,dd=>11}). 200 2> a:a(#{state => {ok,200},id=>123,dd=>11}). 200 3> a:test(#{state => {ok,200},id=>123,dd=>11}). 200 4> 4> |
maps模块方面不知道变动还会有多少,就眼下提供的函数和EEP中的描写叙述还是有不少细微区别的,比方foldr foldl所有整合为fold函数;这个代码太长了,折叠一下:
1
2
3
4
5
6
7
8
9
10
|
11> M= #{a=>123,b=>100}. #{a => 123,b => 100} 12> M>12. true 13> M> << "12" >>. false 14> M> {a,b}. true 15> M > [1,2]. false |
lists:sort([list_to_tuple(maps:to_list(M)) || M <- [M1,M2]).
运算符优先级
没有应用在Map之间的运算符,仅仅有两个内部的运算符=> :=; => 用于创建和更新k-v, := 用于更新已经存在的k-v, :=在匹配过程用来从指定的key中提取Value值;
Why Maps?
我们已经有了record,dicts,gb_trees,ets,proplists,为什么还要Maps?Maps和现有的数据结构相比,最大的优势就是充分发挥Erlang模式匹配的威力. 我还关心的是之前的问题是否攻克了:
1.能够把record的name用作參数吗?
#RecordName{} 能够吗?
由于没有RecordName的限制了,所以这个问题自然消失;
2.能够把record的filed作为參数使用吗?
1
2
3
4
5
6
7
8
|
Eshell V6.0 (abort with ^G) 1> M=#{a=>{1,2},b=>23,<< "OK" >> =>ok, f=>fun()->receive a -> "Got a!" end end}. #{a => {1,2},b => 23,f => #Fun<erl_eval.20.101568567>,<<"OK">> => ok} 2> N=a. a 3> #{N := Data} =M. * 1: illegal use of variable 'N' in map 4> |
而在代码模块中,以下的代码也会报错:illegal use of variable 'N' in map
test3(N,#{N := Data}=M)->
Data.
3. a.b.c.d.e.f 能实现吗?
1
2
3
4
5
6
|
1> M = #{ 1.1 => a, 1 => #{ 1 => b } }. #{ 1 => #{ 1 => b }, 1.1 => a }. 2> #M.1.1. a | b ? |
4.record转proplists proplists转record
如今已经没有必要转换了
5.key仅仅能是atom
Maps中的Key能够是随意Erlang terms .
6.record往往要定义在hrl中
不须要了.
那就如今的情况,Maps会替代Record吗?
EEP43 的重要根据是Richard O'Keefes 的 No more need for records (fifth draft).能够说Maps缘起record替换方案.而Maps终于的设计目标是"Maps does not claim to be an replacement to records as the frames proposal does. Instead maps targets a larger usage domain and wishes to be a complement to records and supersede them where suitable."
从语言长远发展看,Map假设提供足够的便利,以及性能保障,淘汰掉record是一个开发人员主动选择的自然过程,是一个"Maps不杀record,record却因Maps而死"过程.对于开发人员倒不必有什么恐慌,record不会一夜之间消失,那么多的项目哪会在一朝一夕之间完毕过渡?顺其自然就好.
悬而未决的功能
有些语法特性在EEP43中提到了,可是在当前版本号(17.0-rc2)并没有提供;首当其冲的就是"Accessing a single value",要达到这个目的能够通过模式匹配完毕,也能够通过调用maps:get方法完毕,所以我对这种方法的期待度并不大.
1
2
3
4
5
6
7
8
9
10
11
|
Eshell V6.0 (abort with ^G) 1> M=#{a=>12,b=>200,c=>234}. #{a => 12,b => 200,c => 234} 2> #{b := B}=M. #{a => 12,b => 200,c => 234} 3> B. 200 4> #{b := B,c := C}=M. #{a => 12,b => 200,c => 234} 5> #{b := B,c := C,d:=D}=M. ** exception error: no match of right hand side value #{a => 12,b => 200,c => 234} |
其次就是Map comprehension ,我个人很喜欢list comprehension,所以对这个功能还是很期待的.
M1 = #{ E0 => E1 || K := V <- M0 }
OK,今天就到这里,期待Erlang新版本号的公布.
最后感谢支付宝付款的小伙伴们,昨天早晨老婆跟我说"短信通知有人在支付宝给你打钱了",我还说"这是什么新诈骗手段啊",验证之后真的是很惊喜,谢谢你们的认可和支持,我会继续努力的.

当我们谈论Erlang Maps时,我们谈论什么 Part 2的更多相关文章
- [Erlang 0117] 当我们谈论Erlang Maps时,我们谈论什么 Part 2
声明:本文讨论的Erlang Maps是基于17.0-rc2,时间2014-3-4.后续Maps可能会出现语法或函数API上的有所调整,特此说明. 前情提要: [Erlang 0116] 当我们谈论E ...
- [Erlang 0116] 当我们谈论Erlang Maps时,我们谈论什么 Part 1
Erlang 增加 Maps数据类型并不是很突然,因为这个提议已经进行了2~3年之久,只不过Joe Armstrong老爷子最近一篇文章Big changes to Erlang掀起不小了风 ...
- 当我们谈论Erlang Maps时,我们谈论什么 Part 1
Erlang 添加 Maps数据类型并非非常突然,由于这个提议已经进行了2~3年之久,仅仅只是Joe Armstrong老爷子近期一篇文章Big changes to Erlang掀起不小了 ...
- [Erlang 0121] 当我们谈论Erlang Maps时,我们谈论什么 Part 3
Erlang/OTP 17.0 has been released http://www.erlang.org/download/otp_src_17.0.readme Erlang/OTP ...
- 话题讨论&征文--谈论大数据时我们在谈什么 获奖名单发布
从社会发展趋势的角度,非常明显大数据会是眼下肉眼可及的视野范围里能看到的最大趋势之中的一个.从传统IT 业到互联网.互联网到移动互联网,从以智能手机和Pad 为主要终端载体的移动互联网到可穿戴设备的移 ...
- Erlang运行时的错误
Erlang运行时发生错误时,会返回一些错误信息,理解这些信息,对于学好.用好Erlang来说是必要. Erlang中的运行错误包括:badarg, badarith, badmatch, funct ...
- 当我们看到phpinfo时在谈论什么
我们在渗透测试的过程中,如果存在phpinfo界面,我们会想到什么? 大部分内容摘抄自:https://www.k0rz3n.com/2019/02/12/PHPINFO 中的重要信息/ 关于phpi ...
- 当我们在谈论 DevOps,我们在谈论什么?
Cloud Insight 携手 BearyChat:打造适合运维人员的团队协作工具 走过 C 轮的 OneAPM,旗下的产品已经日渐丰满,从应用性能监控的 Application Insight 到 ...
- 项目 erlang启动时死循环
机子里的otp是新装的 看了一下main 是在util:ensure_started一堆app的时候死讯了, 按照顺序是sasl crypto asn1 public_key ssl 发现是publi ...
随机推荐
- 2014秋C++ 第7周项目 数据类型和表达式
课程主页在http://blog.csdn.net/sxhelijian/article/details/39152703,课程资源在云学堂"贺老师课堂"同步展示,使用的帐号请到课 ...
- swift-初探webView与JS交互
公司接下来的项目需要用swift内嵌h5来实现, 以前没有做过swift项目, 现在慢慢将所学的一点一滴记录一下 一个是怕自己忘了- =, 再就是希望大家看到能帮助我哈哈哈 前几天想要直接用swift ...
- 从Oracle转到Mysql前需了解的50件事
我本人比较关心的几点: 1. 对子查询的优化表现不佳. 2. 对复杂查询的处理较弱 4. 性能优化工具与度量信息不足 12. 支持 SMP (对称多处理器),但是如果每个处理器超过 4 或 8 个核( ...
- Java IO 基础
早上复习了IO.NIO.AIO相关的概念,将其中一些要点记录一下. 从编程语言层面 BIO | NIO | AIO 以Java的角度,理解,linux c里也有AIO的概念(库),这些概念不知道什么原 ...
- USACO 2.2 Runaround Numbers
Runaround Numbers Runaround numbers are integers with unique digits, none of which is zero (e.g., 81 ...
- oracle数据泵备份与还原
完整的常用的一套oracle备份以及还原方案 --在新库中新建数据目录,我没有特别说明在哪执行的语句都可在plsql中执行 CREATE OR REPLACE DIRECTORY dump_dir A ...
- Solidworks.2016.SP5下载安装破解图文教程
安装此软件一定要断网安装!!!下载完成后解压文件,打开破解文件夹,双击文件夹中的SolidWorksSerialNumbers2016.reg进行注册表注册,如下图. 解压软件安装包(或者将软件安 ...
- BZOJ 4516 后缀数组+ST+set
写了一半 没了啊啊啊 重新写的 思路: 先不考虑后缀自动机 (我不会啊) 那这道题只能用后缀数组了 先把原串倒一下 后缀->前缀 相当于每回在前面加了一个字母 求不同的子串个数 首先 正常的求子 ...
- 算法入门经典第六章 例题6-14 Abbott的复仇(Abbott's Revenge)BFS算法实现
Sample Input 3 1 N 3 3 1 1 WL NR * 1 2 WLF NR ER * 1 3 NL ER * 2 1 SL WR NF * 2 2 SL WF ELF * 2 3 SF ...
- TimSort学习资料
深入理解 timsort 算法(1):自适应归并排序 如何找出Timsort算法和玉兔月球车中的Bug? Java TimSort算法 源码 笔记 Timsort https://en.wikiped ...