Erlang的设计理念确实很强_Erlang 程序设计书评-查字典图书网
查字典图书网
当前位置: 查字典 > 图书网 > > Erlang 程序设计 > Erlang的设计理念确实很强
序进 Erlang 程序设计 的书评 发表时间:2013-09-30 08:09:18

Erlang的设计理念确实很强

【数据类型篇】

数字(integer + float)和原子(atom)是最基础的常量,说它们最基础,是因为它们没有结构。数字可以计算,原子不可以计算(只能进行比较)。Erlang支持任意长整数的计算,浮点数的计算精确到小数点后16位数,你可以理解为1/(10^16)就是所谓的“1”,在此基础上的任意“长整数”的计算。

元组(tuple)和列表(list)是建立在数字和原子的基础上,有一定结构的常量,你说是数字和原子的结构也对。tuple把固定数目的item聚集在一起,类似C中的array或struct,而list把不定数目的item聚集在一起,类似C中的stack,我们很容易在开头添加或删除item,而保持list类型不变。正因为如此,我们可以用tuple模仿list,从某种程度说,list不过是tuple细分出来的一个常用的结构形式罢了,但在实现上性能可能进行了优化。tuple可以嵌套,类似C中的tree,list也可以嵌套,但是现实意义不是很大。
记录(record)之于元组(tuple),就好比字符串(string)之于列表(list)。记录是元组的变种,本质上还是元组,字符串是列表的变种,本质上还是列表,它们都是为了更好的可读性而产生的。record在tuple的基础上,对每个item进行命名(关键字与值一一对应),而无需频繁地在tuple中插入原子增加可读性,这样可以节省大量的成本;string在list的基础上,限制每个item只能是printable character对应的整数,不论是输入字符串还是输出字符串,都变得更加人性化了。至于string为什么不是tuple而是list,可能是因为字符串处理,list相对于tuple来说更加灵活。

在Erlang中,“变量”并不是通常所说的变量,它一旦赋值就不能修改,就好比取名字一样,我们管这个人叫“张三”,就不能等下又管另一个人叫“张三”,这样我们沟通起来就不会产生误会,同样,在Erlang中,进程之间为了沟通起来不会产生误会,一旦“变量”指代了某个常量,它就不能指代为其他常量。所以Erlang的“变量”叫做名字更加贴切,而所谓的“赋值”与其说是一次性赋值,不如说是绑定,而绑定后调用=操作就叫匹配,叫好比有个新的名字,刚开始大家都没有用它来指代某个人,第一次使用=操作后,这个新的名字与某个人发生了绑定,往后再使用=操作,就都是匹配了。同样,与其说=是赋值号,不如说它是绑定号或匹配号。

模块(module)类似Java的package,把多个函数打包在一起,在erl中不能像在module文件中那样直接定义函数,只能创建匿名函数(anonymous function)。
> fun(X) -> X * X end (9).
你也可以绑定该匿名函数到某个变量重复使用。
> Square = fun(X) -> X * X end.
> Square(9).
说到函数的绑定,如果需要绑定某个module的函数到某个变量中,需要用到函数引用(function reference):fun Mod:Func/Arity(如果引用当前module的函数,Mod可以不写),在Erlang中,同一个module的两个函数即使名字相同,只要参数的个数不同,就是两个不同的函数。
> Max = fun erlang:max/2.
> max(2, 3).
匿名函数和函数引用,在某种程度上,是同一个概念来的,因为它们都可以作为其他函数的参数,这样就产生了高阶函数,而Erlang之所以叫做函数编程语言(functional programming language),也正是因为函数的参数还可以是函数。

guard不知道怎么翻译,它是一个关系表达式或BIF(erlang模块的函数),对于模式匹配(pattern matching)来说,显然它是一个很好的补充。对于函数来说,真正的匹配,不单单是一个模式上的匹配,还需要满足其他的条件,而这恰好就是guard的强项,就好象多个保卫(guard sequence)一样,共同保护守卫着模式匹配。在逻辑学上,guard就是一个谓词,guard sequence就是一个没有量词的析取范式,";"就是∨,","就是∧,结果就是true或false。
说到模式匹配和guard,就不得不提到case表达式和if表达式,当函数的部分参数需要进行模式匹配和guard,而其他部分与之无关时,如果使用外部的模式匹配和guard的话,会搞得相当复杂(如clause数增多,逻辑不清晰,出现重复代码,性能下降等),这时候就可以在内部使用case表达式对这部分参数进行模式匹配和guard,同样,当guard也会引起类似的复杂度时,我们也可以在内部使用if表达式进行描述。可以说,case表达式是模式匹配+guard的一种辅助,而if表达式则是guard的一种辅助,你说if表达式是case表达式的简化版也没错,因为case表达式确实也包含了guard的功能。

binary(二进制)这个类型,顾名思义,就是为了能够把数据粒度细到一个binary(bit)而产生的。我们知道,大的integer为bignum类型,tuple和list有一定结构,空间利用率都不是很高,当存储或传输它们时,就会增加不必要的成本,我们可以通过某个协议(the Erlang external term format)压缩成一串字符(raw data),而压缩后的类型就是binary了,当存储或传输完后,我们可以再通过这个协议解压还原出最初的数据。Erlang的任何数据类型,通过term_to_binary/1和binary_to_term/1两个函数,都可以与binary进行互换。binary没有嵌套,即没有结构,只是一块扁平化的连续内存空间,它的每个item只能是0~255的整数或字符串,因为0~255的整数和字符都可以用一个字节表示,使得binary的数据粒度细到一个byte(8个bit),而真正让binary的数据粒度细到一个bit的是the bit syntax,它使得每个item的大小不必是8个bit的倍数,而可以是任意的bit数,只要所有item的bit数加起来是8个bit的倍数即可。

进程词典(process dictionary)是一个小型的key-value数据库,每个进程(process)都有一个。由于我们可以修改每个key对应的value,可能会产生side effect,所以不到万不得已,尽量不要使用,当然啦,如果只是用来存储write-once variable,那是非常合适的。

reference意思为编号或标记,Erlang能够保证make_ref/0产生的任意两个reference都不相同,也就是说,reference是用来产生唯一的标识符的,主要在远程过程调用(rpc)中用来标识消息(message)。

【并发进程篇】

待续。。。

展开全文
有用 1 无用 0

您对该书评有什么想说的?

发 表

推荐文章

猜你喜欢

附近的人在看

推荐阅读

拓展阅读

对“Erlang的设计理念确实很强”的回应

lili 2014-10-24 14:43:58

用得多了,你就知道坑在哪了。。。

掩面张三 2013-12-12 17:52:07

模块(module)类似Java的package,把多个函数打包在一起,在erl中不能像在 module文件中那样直接定义函数,只能创建匿名函数(anonymous function)。

这从哪看的?确定没问题?

foo () -> bar.

这不是函数了嘛?