天天看点

感受 Erlang(1)

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 的语法非常简单明瞭。

继续阅读