Erlang学习札记001-入门

Erlang学习笔记001--入门
一、erlang入门
1、erlang的安装。
    我建议使用debian系的linux来进行erlang的学习,因为在debian系的linux上,erlang的安装是非常简单的,我们不需要花费一整天的时间来搭建一个舒心的环境。
    在debian系的linux上安装erlang环境只需要一个简单的命令:
        apt-get install erlang;
 当然,我们还需要超级用户的权限,所以在大部分情况,我们需要的命令是:
        sudo apt-get install erlang;
    不需要任何额外的设置,安装就完成了。输入erl,如果显示如下内容,那么就大功告成了!
        Erlang R14B04 (erts-5.8.5) [source] [64-bit] [rq:1] [async-threads:0] [kernel-poll:false]


        Eshell V5.8.5  (abort with ^G)
        1> 

    现在我们可以进入下一步,erlang shell的简单使用。
2、Erlang shell
    在console输入erl,就可以启动Erlang shell
        Erlang R14B04 (erts-5.8.5) [source] [64-bit] [rq:1] [async-threads:0] [kernel-poll:false]


        Eshell V5.8.5  (abort with ^G)
        1> %This is a shell show.
        1> 20+30.
        50
        2> 

    上面的演示基本参照Joe Armstrong的《Erlang Programming》。下面来分析一下,启动Erlang shell之后,程序显示了提示符1>,而我们输入了"%This is a shell show.",这里百分号%代表这行从百分号开始后面的是注释,不作为程序执行。接下来我们输入了"20+30.",这里需要注意的是,Erlang的表达式都是以"."结束的,如果忘了,Erlang shell会认为表达式没有结束而不给出结果,如果发现输入了表达式而shell给出一个同样行数的输入提示而不给出结果,首先检查结束符。当我们继续输入换行(回车)后,shell给出了我们输入的表达式的结果,然后出现了"2>"提示这是本次启动shell的第二个表达式的开始。
    Erlang shell提供了一些比如[C-n],[C-p],[C-f],[C-b]之类emacs风格的快捷键来帮助找回和修改使用过的表达式,如果要进一步学习,需要查阅一些相关的文档。
3、算术表达式
    如同介绍Erlang shell所输入的表达式一样,我们可以在shell输入几乎任意的算术表达式,比如说
        10+3*60.
        1234567*1234567*1234567*1234567*1234567.
    对于上面第一个表达式,其计算规则将符合四则运算法则,先做乘法然后做加法,而不是从左到右的计算。对于第二个表达式,作为一个c++程序员,我惊叹了,Erlang的整数显示就像没有位数限制一样。(事实上,我必须说,接触到和自己一贯熟悉的东西非常不同的机制,给人很特别很有趣的体验)。下面看看结果:
        2> 10+3*60.              
        190
         3> 1234567*1234567*1234567*1234567*1234567.
         2867961522709958332493501997607
         4> 

4、变量
    Erlang的变量赋值形式大概是这样的: 
        X=1234567.%变量赋值也是表达式,要以结束符结尾。
    这样子我们就把1234567赋给了变量X。Erlang中的变量和我们常见的c/c++一系的语法不同,Erlang的变量只允许单次赋值,一旦你给了变量一个初始值,在变量的生命周期中,它将不会改变,如果你想获得一个由该变量计算所得的值,类似c语言中的X++,那你仍然必须声明另一个变量。当你尝试使用"="改变一个已赋值的变量,程序将抛出一个错误。类似以下所展示的一样:
        4> X=1234567.
        1234567
        5> X=2345.
        ** exception error: no match of right hand side value 2345
        6> 

    我们查看关于这个异常的说明,"no match of right hand side value 2345",用中文来说,就是"无法和右边的值2345进行匹配",这是一个奇怪的提示,如果我们把等号看作赋值运算符的话。就其本质来说,Erlang中的等号应该被看作一个模式匹配运算符而不是一个赋值运算符,关于模式匹配,我们将在以后再深入解释。
    Erlang的变量只允许单次赋值,每次对已有变量进行运算之后都必须声明新的变量来保存,这在一开始让我有一种想法“那变量名称管理就麻烦了,这比可得多声明不少变量”,但事实上,我担忧的问题并不存在。Erlang中每个变量的生命周期都只在它被声明的函数运行过程,而与函数外或者被他调用的函数无关,如果不是我们写了一个其长无比,里面包含大量的变量,应该不会出现命名上的困扰。
    需要注意的是:变量命名必须以大写字母开头。
5、原子
    原子在Erlang中用来表示不同的非数字常量。如果用c/c++中的什么来做类比,感觉都并不是特别合适,还是举几个例子来说明:
    原子有两种形式,一种是以小写字母开头,后跟着字母数字或者某些字符,比如说@或者下划线_的一串字符。例如:red,green,oranges,mid_street等等。第二种则是用单引号括起来的字符串,这个字符串可以以大写字母开头,也可以包含一些非数字的符号。
    这里要注意的是如果一个用单引号括起来的原子,去掉单引号之后也是一个合法的原子表示,那么两者代表的是同一原子,比如'red'和red代表同一个原子。
    原子具体是什么并不重要,重要的是不同原子在程序中是可区分的,代表不同的东西,在这个意义上来说,有点像枚举,通过原子我们可以标志不同的事物,并且提供可读性。比如可以用monday、tuesday等原子来标志一周中的一天。就像我们在c语言也会如下这么做类似:
        enum
        {
            Monday=0,
            Tuesday,
            ...,
            Sunday
        }
    上述枚举的例子我省略了一些,请大家不要太追究。
6、元组
    元组的作用有点像c语言的结构体,如果需要用一组属性来标志一个对象,那么我们会用到元组。元组是用大括号括起来用逗号分隔的一个序列,比如:
       {orange, orange}, {10,45}
    我们可以把项组赋给变量,同时项组也可以嵌套,以下例子演示了这个特性:
       Y={fruit, {orange, apple}, 10}.
    下面再简单演示一下如何获取元组Y中的第二个元素(也是一个元组),并将它保存到Z中:
        {_,Z,_}=Y.
    下划线这里用来匹配元素,在后面详细介绍模式匹配时会再提到。这里用Z去匹配元组Y的第二个元素,因为Z未被初始化,所以它被赋值。这里的赋值行为和我们讲变量的时用等号赋值是一致的,如果变量未被初始化,则赋值,否则抛出一个异常。
7、第一个Erlang程序
    我不会用Hello,world来作为第一个程序,因为只要你将'Hello,world'这样的原子加个结束符作为表达式,那么Hello,world就输出出来了,这非常无聊。
    现在我们用文本编辑器来写一个可编译的东西,然后在Erlang shell上运行,来当作Erlang程序的简单展示。打开你所喜欢的任何编辑器,vim或者emacs,kate或者gedit,随便都好,输入以下内容,并保存为geometry.erl 
    1    -module(geometry).
    2    -export([area/1]).
    3    area({rectangle, Width, Height}) ->
    4        Width*Height;
    5    area({circle, Radius}) ->
    6        3.1415926535897932384626433832795028869399*Radius*Radius.

    现在我们来看看上面的代码代表什么意思,第一行我们声明了一个模块 geometry,模块是Erlang程序代码中的基本单元,我们编写的所有函数都保存在模块中,并保存为erl文件。以上的模块声明了一个函数area,它的作用是计算形状的面积。这里只定义了对应矩形和圆形的实现。下面我们来编译并试用这个模块。切换当前工作目录到 geometry.erl所在的目录,然后输入erl启动Erlang shell,输入以下命令:
    1>c(geometry).
    如果编译完成则会显示:
    {ok, geometry}
    如果查看目录,我们可以发现多了一个 geometry.beam的文件,这就是模块编译结束的文件。我们可以继续在控制台测试我们的模块:
    2> geometry.area({rectangle, 10, 30}).
    300
    3> 

    可以继续测试圆形等,这里我们可以看到,函数匹配到元组第一个原子rectangle,然后把之后的数值赋给了Width和Height,最后返回了计算值300,达到了我们的预期。






ps. 此文章作为我学习erlang的读书笔记,由我本人手打,例子基本摘自《Erlang programming》,如果转载请注明出处。如果认为有学习价值,请大家收藏本博客,并欢迎留言讨论,本学习笔记会持续更新。