Erlang 的学习感受
Erlang 是个好东西,并发控制、容错机制、分布应用,……,简直是个高级实用技术仓库。在它适用的领域里,Erlang 有着独步天下的优势,至今没有别的语言工具能与它叫板抗衡。
最近,开始学习 Erlang,看了几天的e教材后,有些相见恨晚的感叹。为了提醒备忘,把一些收获感受写下来。
一、怎样快速入门
现在,从网上能很容易地找到一大堆 Erlang 的中英文资料。虽说开卷有益,但我觉得最好的入门教材,是 Erlang 自带的 doc,即《Getting Started With Erlang》。
在学习方法上,按照循序渐进的规律,在入门阶段,记忆比理解更重要。首先囫囵吞枣,比着葫芦画瓢,了解对象的全貌,快速掌握基本内容。然后反复温习,攻读实例代码,深入理解,最后达到熟练、精通。
二、Erlang = Prolog + Lisp
从基本语法上,Erlang 是 Prolog 和 Lisp 的混合杂交产物。
Erlang 诞生地是瑞典。同在斯堪的那维亚半岛上的瑞典和丹麦,人工智能研究颇有名气,象丹麦的Visual Prolog(前身是PDC Prolog, Turbo Prolog),Hugin(贝叶斯置信网络系统),瑞典的 SICStus Prolog。Erlang 的初始版本是用 Prolog 写成,与这个背景不无关系。
大致粗略地看,在基本语法上,Erlang 与 Prolog 有以下相似之处。
● 语句分隔符是逗号(,),语句(子句、段)结束符是句号(.)
● 变量名称第一个字符必须用大写字母
● 在同一作用域,变量只能一次赋值
● 以下划线作为匿名变量
● 数据类型:atom(原子),以小写字母开头,可简单地看作是没有引号的字符串
● 函数子句(clause)及其匹配(match)的概念
● 注释符号相同(%)
● 分号(;)在 Prolog 中是逻辑“或”(or)的句段分隔符,在 Erlang 中大体意思相同
● 列表(list)的表达和操作几乎完全相同
● 列表 list 是 prolog 最重要的数据结构,在 erlang 中似乎也是
● 同名函数(子句)以形参数目相区别
● 都使用子句匹配的递归循环,都没有 for、while 循环方式
从词法、句法、章法上,erlang 的语法相似于 prolog。词法:变量首字母大写;句法:子句;章法:子句匹配,递归循环。
Erlang 与 Lisp 相似之处,即它具有的函数语言的特征。
● 子句分成首体 2 部分,符号(->)前面的是子句头,后面的是子句体
● 有 lambda 高阶函数语法机制
Erlang 虽然同时具备 Prolog 和 lisp 的特征,但主要的、大部分的特征更象 Prolog。因此,把 Erlang 当做逻辑式函数语言,会更有利于对它的理解掌握。
三、对 Erlang 实用化的理解
对许多人来说,Erlang 的语法(包括词法、句法、章法)有些怪异。这是因为 Erlang 的编程方式,基本上是“说明式”的,不是人们熟悉的“过程式”的。解决这个困难问题的办法之一,是对 Erlang 作“过程式”的解释。
以计算阶乘的函数子句为例:
fac(1) ->
1;
fac(N) ->
N * fac(N - 1).
做点修改可能看得更清楚些:
fac(1) ->
1;
fac(N) ->
M = fac(N - 1),
N * M.
它的本意是:如果参数值为1,返回 1;否则,求出 N - 1 的阶乘 M,返回 N 与 M 的乘积。
其实,Erlang 子句的结构形式,与 Prolog 一样,具有逻辑编程的意义,在符号 -> 前面的是测试判断的条件,后面的是测判后的操作行为结果。分号(;)在此是or(否则)的意思。
由于第二个子句是递归循环,于是,第一子句也是递归循环终止的限制条件。
翻译成 c 语言程序,代码是这样的:
int fac( n )
{
if (n==1)
return (n);
else
return (n * fac(n - 1));
}
以上是2个子句一组的函数,构成 if-then-else 的逻辑关系。
Erlang 也有1个子句的函数,表示 if-then 的关系。如:
start() ->
spawn(tut14, say_something, [hello, 3]),
spawn(tut14, say_something, [goodbye, 3]).
这种没有形参的函数,相当于 if true then: 的无条件执行,即“过程式”函数。
对于 if-then-else 嵌套的逻辑,Erlang 是这样处理的:
● guard 机制。如:
list_max([], Res) ->
Res;
list_max([Head|Rest], Result_so_far) when Head > Result_so_far ->
list_max(Rest, Head);
list_max([Head|Rest], Result_so_far) ->
list_max(Rest, Result_so_far).
第2子句首部多了个 when 测试。它实际上是 if 判断,逻辑行为如下:
if (Head > Result_so_far)
执行本子句(第2子句)中的语句;
else
执行函数的第3子句;
● if 机制,case 机制。如:
month_length(Year, Month) ->
Leap = if
trunc(Year / 400) * 400 == Year ->
leap;
trunc(Year / 100) * 100 == Year ->
not_leap;
trunc(Year / 4) * 4 == Year ->
leap;
true ->
not_leap
end,
case Month of
sep -> 30;
apr -> 30;
jun -> 30;
nov -> 30;
feb when Leap == leap -> 29;
feb -> 28;
jan -> 31;
mar -> 31;
may -> 31;
jul -> 31;
aug -> 31;
oct -> 31;
dec -> 31
end.
总之,以上大致是 Erlang 基本语法的主要内容。应该说,Erlang 的语法非常简单明瞭。