感受 Erlang(1)

童铭晨
2023-12-01
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 的语法非常简单明瞭。

 类似资料: