天天看点

Erlang程序设计

Erlang程序设计笔记

1.什么是并发?

1.1 给并发建模

1.1.1 开始模拟

spawn: spawn是一个Erlang基本函数,它会创建一个并发进程并返回一个进程标识符。

spawn的调用方式: spawn(ModName, FuncName, [Arg1, Arg2,…,ArgN])。

  • ModName:想要执行代码的模块名。
  • Function:模块里的函数名。
  • [Arg1, Arg2,…,ArgN]:一个列表,包含了想要执行的函数参数。
  • Spawn返回的是一个进程标识符(PID,Process IDentifier),可以用来与新创建的进程交互。

1.2 并发的好处

性能

可扩展性

容错性

清晰性

2.Erlang速揽

2.1 Shell

2.1.1 =操作符

Erlang单词赋值: Erlang是一种函数式语言,只能单次赋值,Erlang的变量只能绑定一次,不能重新绑定变量。

=: =不是赋值操作符,其实是模式匹配操作符。

2.1.2 变量和原子的语法

Erlang变量: Erlang变量都是以大写字母开头,以小写字母开头的是符号常量,它们被称为原子(atom)。

3.基本概念

3.1 启动和停止Erlang Shell

3.2 简单的整数运算

Erlang整数: Erlang可以用任意长度的整数执行整数运算,在Erlang里,整数运算时精确的,无需担心溢出或无法用特点字长来表示某个整数。

3.3 变量

变量: 所有变量必须以大写字母开头,变量只能被一次赋值,Erlang中的变量都是一次性赋值变量。已经被指派一个值的变量称为绑定变量,否则称之为未绑定变量。

=: 不是赋值操作符,而是一个模式匹配 操作符。=在变量未绑定之前表现类似于赋值。

可变状态: 可以修改的内存区域专业术语叫做可变转态。Erlang是一种函数式编程语言,具有不可变状态。

一次性赋值的优势: 在Erlang里,变量只不过是对某个值的引用,Erlang的实现方式用指针代表绑定变量,指向一个包含值得存储区,这个值不能被修改。

3.4 浮点数

3.5 原子

原子: 在Erlang中,原子被用来表示常量值。原子是全局性的,不需要宏定义或包含文件就能实现。

原子的格式: 以小写字母开头,后面接字母、数字、下划线或at(@)符号。原子还可以放在单引号内(‘’),可以用这种引号形式创建以大写字母开头(否则会被解释成变量)的或包含字母、数字以外字符的原子,例如‘Monday’, ‘+’, ‘*’ 或’an atom with space’。甚至可以给无需引号的原子加上引号,因此‘a’和a的意思完全一样。Erlang中单引号和双引号不可以互换使用(某些语言中可以互换使用),Erlang中双引号用于给字符串字面量定界。

3.6 元组

元组: 创建元组的方法是用大括号把想要表示的值括起来,并用逗号分隔它们。元组可以嵌套。元组会在声明它们时被主动创建,在不用它们时被销毁。Erlang会使用垃圾收集器来回收所有未使用的内存,这样不用担心内存分配问题。

Person = {person, {name, joe}, {height, 1.82}}.
           

3.7 列表

列表: 列表被用来存放任意数量的事物,创建列表的方法是用中括号把列表元素括起来,并用逗号分隔它们。列表中的各元素可以是各种类型的。

列表头和列表尾: 列表的第一个元素被称为列表头,其它的元素被称为列表尾。

3.8 字符串

字符串: Erlang里面没有字符串,要在Erlang中表示字符串,可以选择一个由整数组成的列表或者一个二进制型。当字符串表示为一个整数列表时,列表里的每个元素都代表了一个Unicode代码点(codepoint)。可以用字符串字面量来创建这样一个列表,字符串字面量其实就是用双引号围起来的一串字符。

Name = "Hello".
           

"Hello"其实只是一个列表的简写,这个列表包含了代表字符串里各个字符的整数字符代码。

字符串标记: Erlang中字符串使用双引号标记。当shell打印某个列表的值时,如果列表内的所有整数都代表可打印字符,它就会将其打印成字符串字面量,否则,打印成列表记法。

2>[1,2,3].
[1,2,3]
3>[83,117,114,112,114,105,115,101].
"Surprise"
4>[1,83,117,114,112,114,105,115,101].
[1,83,117,114,112,114,105,115,101]
           

3.9 模式匹配再探

4.模块与函数

4.1 模块是存放代码的地方

模块: 模块是Erlang存放代码的地方,模块保存在扩展名为.erl的文件中,编译后的模块以.beam为扩展名。

-module().: 模块申明,申明里的模块名必须和存放该模块的主文件名相同。

-export().: 导出申明。Name/N这种标记方法是指带有N各参数的函数Name,N被称为函数Name的元数 。未从模块里导出的函数只能在模块内部调用,已导出的函数相当于面向对象编程里的公共方法,未导出的函数相当于面向对象里的私有方法。

函数: 如下所示,函数有两个子句,每个子句以分号隔开,最后的子句以句号加空白结束。每条子句都有一个头部 和一个主体 ,两者用箭头分隔,

area({rectangle, Width, Height}) -> Wight * Height;
area({square, Side}) -> Side * Side.
           

逗号(,): 分隔函数调用、数据构造和模式中的参数。

分号(,): 分隔子句。

句号(.): 分隔函数整体,以及shell里的表达式。

4.2 继续购物

4.3 fun:基本的抽象单元

fun: Erlang是一种函数式编程语言。函数式编程语言还可以表示函数可以被用作其它函数的参数,也可以返回函数。操作其它函数的函数被称为高阶函数 。Erlang中用于代表函数的数据类型被称为fun。

以fun作为参数的函数: 标准库里的lists模块导出了一些以fun作为参数的函数。

返回fun的函数: 函数不仅可以使用fun作为参数(例如map和filter),还可以返回fun。

例子:括号里的东西就是返回值。

1>Fruit = [apple, pear, orange].
[apple, pear, orange]
2>MakeTest = fun(L) -> (fun(X) -> lists:member(X, L) end) end.
3>IsFriut = MakeTest(Friut).
返回:IsFriut = MakeTest(Fruit) = fun(Fruit) -> (fun(X) -> lists:member(X, [apple, pear, orange]) end) end.
	 IsFriut = fun(X) -> lists:member(X, [apple, pear, orange]) end.
4>IsFruit(pear).
true
5>IsFruit(apple).
true
6>IsFruit(dog).
false
           

4.4 简单列表处理

4.5 列表推导

列表推导(list comprehension): 是无需使用fun、map或filter就能创建列表的表达式。

4.6 内置函数

内置函数: 内置函数简称为BIF(built-in function),是哪些作为Erlang语言一部分的函数。有些内置函数是用Erlang实现的,但大多数是用Erlang虚拟机里的底层操作实现的。内置函数能够提供操作系统的接口,并能执行那些无法用Erlang编写或者用Erlang编写比较低效的操作。比如,你无法将一个列表转化为元组,或者查到当前的时间和日期,要执行这样的操作,需要调用内置函数。所有的内置函数都表现的像是Erlang模块的,但那些最常用的内置函数(如list_to_tuple)是自动导入的。

4.7 关卡

关卡(guard): 关卡是一种结构,可以用它来增加模块匹配的威力。通过使用关卡,可以对某个模式里的变量执行简单的测试和比较。

关卡系列: 关卡序列(guard sequence)是指单一或一系列的关卡,用分号(;)分隔。对于关卡序列G1;G2; …; Gn,只要其中有一个关卡(G1、G2……)的值为true,它的值就为true。关卡由一系列关卡表达式组成,用逗号(,)分隔。关卡GuardExpr1, GuardExpr2, … ,

GuardExprN只有在所有的关卡表达式(GuardExpr1、GuardExpr2……)都为true时才为true。

4.8 case和if表达式

case语法:

case Expression of
	Pattern1 [when Guard1] -> Expr_seq1;
	Pattern2 [when Guard2] -> Expr_seq2;
	...
end
           

case执行过程如下:首先计算表达式Expression的值,假设它的值为value,接下来value值轮流与Pattern1、Pattern2进行模式匹配,直到匹配成功。一旦匹配成功,相应的表达式就会执行;如果所有表达式都不匹配,就会发生异常错误。

4.9 构建自然顺序的列表

5.记录与映射组

记录: 记录其实是元组的另一种形式,通过使用记录,可以给元组里的各个元素关联一个名称。

映射组: 映射组是键值对的关联集合。键可以是Erlang的任何数据类型。

5.1 何时使用映射组或记录

5.2 通过记录命名元组里的项

记录: 记录的语法格式

record{Name, {
              %%以下两个键带有默认值
              key1 = Default1,
              key2 = Default2,
              ...
			  %%下一行就相当于key3 = undefined
			  key3, 
             }
      }