erlang学习1 -- 入门

来源:互联网 发布:js 列表金额合计 编辑:程序博客网 时间:2024/04/28 16:01

今天下载了JOE ARMSTRONG的《Erlang程序设计》一书,没想到JOE ARMSTRONG的博士论文我曾经下载过,可惜没时间看,这个绝对是分布式领域的大牛!!

经过一番折腾后,终于有时间静下心来看看这本书,并对学习作一点记录:

1、如何打开Erlang shell:直接输出erl即可;

2、erlang shell中以%表示一个注释的开始,从百分号开始到这行结束的所有文件都被看作是注释;

3、每一个表达式的结尾必须紧跟一个句号和一个回车(没有句号,erlang就认为还没有输完整个表达式,不会有结果);

4、erlang采用不定长的整数来进行整数算法运算,没有误差,不用担心运算溢出;

5、可以用不同的方式输入整数,如输入16进制数10:16#10。16#abc * 32#def表示16进制数abc与32进制数def相乘;


变量

1、变量的赋值:X=123.

表示把123赋给变量X。在erlang中,所有变量都以大写字母开头。

2、变量不变性

erlang的变量是单一赋值变量,只能一次性给定变量值,否则报错。

一个变量如果含有一个被赋予的值,就称为绑定变量,否则,被称作自由变量,一开始,所有变量都是自由的。

在被绑定之前,X可以接授任何值,一旦得到了某个值,那么它就永远保持这个值。

3、变量作用域

定义一个变量的词法单元就是这个变量的作用域,离开了词法单元,X的值就互相独立。

4、模式匹配(以下内容慎点,有点绕)

在erlang中,=表示一个模式匹配操作。A=B实际上是这样一个过程:对右端B求值,然后将结果与左端A进行模式匹配。

当我们第一次输入A=SomeExp时,erlang会尝试如下操作:要怎么做才能让这个语句的值变为true?由于A一开始是自由变量,因此可以把SomeExp的结果绑定到A上,同时也使得语句为true,皆大欢喜。

但是,如果随后又输入A=AnotherExp时,只有当SomeExp与AnotherExp一致时,这个语句才会成立,即为true而不报错。

实现原理:shell中维护了一张绑定表{A->SomeExp,B->SomeExp2},如果运行A=B,则会发现匹配失败,报错

5、为什么要有变量的不变性?

首先要理解erlang中变量的实现机制:一个绑定变量就是一个指针,这个指针指向存放那个值的存储区,而那个值是无法改变的。注意,理解这一点很重要!

X=23.。Y=4*X+3.。如果此时X的值可以改变,由于X是个指针,必然导致Y的值也会发生改变!Y的值也就不正确了,不能把语句2看作是一个等式,即模式匹配不为true!

erlang的这种设计是为了防止变量在运行过程中被意外修改,而导致运行结果不正确,当程序中有多处地方修改变量的值时,这个问题更加严重。如果用C等传统的编程语言为多核CPU编写程序时,就不得不应付共享内存带来的问题,如加锁等。erlang没有可修改的内存区域,也就没有共享内存,更没有锁,这一切都有利于并行化程序的编写。

erlang中如何实现X=X+1的操作?声明一个新变量,它的名字之前没有被用过,如X1=X+1.


浮点数

1、5/3. -->  1.6667  4/2. --> 2.00000   5 div 3. --> 1  5 rem 3. --> 2  4 div 2. --> 2

如果有表过一个浮点数,变量要写成3.0,不能是“3.”,因为erlang会认为这是一个句号,表示表达式结束,浮点数必须含有小数点且小数点后至少有一位十进制数

2、/永远返回浮点数,结果会自动转为浮点数,因此4/2结果是2.0000。div 是用于整数除的,div用于取于余数


原子

1、在erlang中,原子用来表示不同的非数字常量值。类似于C中的全局常量#define SUCCESS 1这种。相同名字的原子全局唯一,不需要使用任何宏定义或者包含文件,可以表示某个不变的值。

2、原子以一串小写字母开头,后跟数字字母或者下划线,如monday、success、fail等,使用单引号引起来的字符也是原子,使用这种形式,就能使得原子可以用大写字母作为开头或包含非数字字符(注意区别变量名命名规则),如'Monday'、'Success'等

3、一个原子的值就是原子自身,而且是全局唯一的

4、原子可以这样使用:

传统的C:

#define OP_READ 1#define OP_WRITE 2#define SUCCESS 1#define FAIL 2int ret; ret = file_operation(OP_READ,buff);if( ret == RET_SUCCESS )    ...
erlang:无需定义专门的宏,原子本身就是一个值

Ret = file_operation(op_read,Buff);if   Ret == ret_sueccess...


元组

1、元组可以将一定数量的项组成单一的实体,将若干个以逗号分割的值用一对花括号括起来,就形成了一个元组。例如要描述某个人的名字和他的身高,可以用{jia,1.76},包括了一个原子和一个浮点值。

2、erlang没有类型声明,因此创建一个point会是这样子:P={10,45}.表示将元组绑定到变量P。注意,元组中的字段没有名字,我们必须记住其用处,但通常可以使用一个原子作为元组的第一个元素来标明这个元组所代表的含义,例如可以用{poing ,10,45}代表一个点坐标。

3、元组可以嵌套:
Person = {person,{name,jia},{height,1.76},{footsize,42}}.
如果创建的一个新元组引用了一个已绑定的变量,那么新元组就会享有这个变量所引用的数据结构:
F = {firstname,jia}.
L= {lastname,guojia}.
P = {person,F,L}.  --> {person,{firstname,jia},{lastname,guojia}}.

4、从元组中提取字段值。

实际为模式匹配操作,利用=的特性:

Point = {poing,10,45}.
如要从Point从提取出字段后存放到X、Y变量中,可以这么做:{point,X,Y} = Point.。背后的原理:等号要匹配两端的值,于是就给X赋为10,Y赋为45

当元组较为复杂时,可以使用_作为占位符,只提取出我们关心的变量:
Person = {person,{firstname,jia},{lastname,guojia}}.
{_,{_,Firstname},_} = Person
变量Firstname被赋为jia


列表

1、用列表存储数目可变的东西,将若干个逗号分割的值用一对方括号括起来,就形成了一个列表。例子:
ThingsToBuy  = [{apple,10},{pears,6},{milk,3}].

2、如果T是一个列表,那么[H|T]也是一个列表,以H为头,T为尾,竖线符号|可以将列表的头和尾分隔开来,可以用[E1,E2,...,En|T]的方式向T的起始处加入多个新元素,如:
ThingsToBuy1 = [{oranges,4} | ThingsToBuy]. --> [{oranges,4},{apple,10},{pears,6},{milk,3}]
注意区别元组:元组也可以组合,但不是严格意义上的添加,元组是以一个整体加入的

3、从列表中提取元素。

同样使用模式匹配从一个列表中提取元素,如:
[Buy1 | ThingsToBuy] = ThingsToBuy1. --> Buy1={oranges,4}
如果|符号前只有一个变量名,则会提取ThingsToBuy1中的头元素(即第一个元素)
[Buy1,Buy2 | ThingsToBuy] = ThingsToBuy1.这样会提取ThingsToBuy1中的第一、二个元素赋给Buy1、Buy2


字符串

1、严格来讲,erlang中并没有字符串,字符串实际上就是一个整数列表(实际上是一个列表),用“”将一串字符括起来就是一个字符串,如:
Name = "Hello".
erlang打印一串列表值时,只有列表中的所有整数都是可打印字符,它才把这个列表当作字符串来打印
[83,117,114,112,114,105,115,101].  -->  "Suprise"

2、可以用$来表示字符的整数值。例如:
I = $s.  --> I = 115


再论模式匹配



0 0