Erlang基础

数据类型:

1.整数

1.1.正整数或者负整数,没有最大的正整数,例如-234,0,10000

1.2.Base#Value用于表示基数不为10的整数,Base是一个介于2-16的整数,Value就是基于Base的具体数值,例如2#1010,-16#EA。

1.3.字符的ASCII码,采用$Character的表示方法,例如$a,$A,$\n.

2.浮点数(代表实数)

2.1.普通浮点数:17.368,-56.654

2.2.E-10常规的浮点数:1.234E-10和0.0000000001234.

3.基元(文字常量)

3.1.Erlang中的基元类似于其他语言的枚举类型。

3.2.唯一可用于基元的操作是比较。

3.3.基元由小写字母或者单引号界定,当基元用小写字母界定时,字母,数字,@符号,英文句点(.)和下划线(_)都是有效的字符;如果一个基元用单引号封装起来,则可以使用任意字符。

4.布尔类型

4.1.Erlang中没有单独表示布尔类型的布尔值或者字符,基元true和false和布尔操作符一起使用,而不是布尔类型。

4.2.基元按照字典顺序来排序。Erlang中有各种各样的内置函数,通常在社区中被称作BIF。

4.3.内置函数is_boolean用来测试一个Erlang值是否是布尔类型。

4.4.布尔类型的运算(and:如果两个参数都是真,那么就返回真;andalso:and的快捷计算形式,如果第一个参数为假,那么就返回假,而不需要计算第二个参数;or:如果两个参数的任何一个为真,那么就返回真;orelse:or的快捷计算形式,如果第一个参数是真,那么就返回真,而不需要计算第二个参数;xor:异或,如果两个参数的任何一个为真,并且另一个为假,则返回真;not:一元否定运算符,如果参数为假,那么就返回真,反之亦然。)

5.元组

5.1.元组是用来保存一组数据元素的复合数据类型,其中数据元素要求是Erlang数据类型,但并不一定是相同的类型。

5.2.元组用封闭的{。。。}表示,而其中的元素用逗号,隔开,例如{123,bcd},{123,def,abc},{abc,{def,123},ghi},空元组{}不包含任何元素。

5.3.当一个元组的第一个元素是一个基元时,称它为标记,例如{person,'Joe','Armstrong'},基元person为标记,这有可能也就表明第二个元素是这个人的名,然后第三个元素是这个人的姓。

5.4.使用第一个位置的标记是为了区分代码中使用不同的元组的不同目的,当错误元组当做一个参数被错误的传递,或者是作为一个函数调用的结果错误地返回的时候,这有助于找到错误的原因,这被认为是Erlang的最佳实践之一。

5.5.Erlang提供了一些内置函数用来设置和检索元组元素的内容,并得到元组的大小,例如:tuple_size({abc,{def,123},ghi})用来获取元组的大小,此元组的大小为3;element(2,{abc,{def,123},ghi})用来获取元组的第二个元素,即{def,123};setelement(2,{abc,{def,123},ghi},def)用来设置元组的第二个元素,设置完成新的元组为{abc,def,ghi}.

5.6.元组中的元素索引是从1开始而不是从0开始。

6.列表

6.1.列表和元组都是用来存储元素集合的,在这两种情况下,它们的元素都可以是不同的类型,而元素数目也可以是任意的。

6.2.Erlang中字符串是作为一种特殊的列表来表示的。

6.3.列表使用封闭的[...]来定义,而它们的元素由逗号隔开,列表中的元素和元组中的元素一样,不一定是相同的数据类型,它们可以自由混合。

6.4.字符和字符串:字符由整数来表示,字符串(由字符组成)则由整数列表来表示。字符的整数值可以通过在字母前加上$符号来得到;Erlang中没有字符串数据类型,在Erlang中,字符串是一个由ASCII码组成的整数列表,并使用双引号("")来表示,因此,字符串"Hello World"实际上就是列表[72,101,108,108,111,32,87,111,114,108,100].

6.5.基元和字符串:

6.5.1.它们处理方式不同:唯一可用于基元的操作是比较操作,可以使用不同的方式处理字符串。例如:可以把字符串"Hello World"分解成["Hello","World"]的列表,而基元"Hello World"就不能这样处理,可以把一个字符串当做一个基元,即把字符串当做一个常量。

6.5.2.它们的效率不同:字符串占用的空间与字符串的大小成正比,而基元在系统表中表示,它仅仅需要几个字节用作索引,而与它的大小无关。当一个程序比较两个字符串时,需要遍历他们并一个一个地比较字符串中的每个字符,而在对基元进行比较时,运行时系统只需要一个比较操作来比较它们的内部标识即可。

6.6.列表的组成和处理

6.6.1.列表和元组的处理方式不同:元组的处理只是提取的具体元素,而列表只要不为空,就可以把一个列表分成头部和尾部,列表的头部是指列表的第一个元素,它的尾部是一个包含所有剩余元素的一个列表,而这个列表可以继续这样分解下去。

6.6.2.列表可以使用[头部|尾部]来构造,这是一个典型的构造器,如果最后一个尾部项是空列表,那么这就是一个正确的列表或者结构良好的列表。

6.6.3.请注意:你必须有一个元素在构造器的左边和一个列表在构造器的右边,它们都由方括号括起来,这样得到的列表就是一个结构良好的列表。

6.6.4.在Erlang中列表并不一定是要结构良好的。在Erlang中应尽量避免使用结构不良好的列表,否则检查代码是错误还是有意这样做是非常困难的。

6.7.列表函数和操作

6.7.1.列表的很多操作都是在lists库模型中定义,通过在函数前面加上模块的名字来调用,并用冒号隔开。

lists:max([1,2,3]):查找列表中的最大值。

lists:reverse([1,2,3]):将列表反序排列。

lists:sort([2,1,3]):将列表排序。

lists:split(2,[3,4,10,7,9]):将列表分成两部分。

lists:sum([3,4,10,7,9]):计算列表的总和。

lists:zip([1,2,3],[5,6,7]):将两个列表根据下标组成新的元组列表。

lists:delete(2,[1,2,3,2,4,2]):删除列表中的第二个元素。

lists:last([1,2,3]):取得列表中的最后一个元素。

lists:member([5,[1,24]]):检测5是否是列表中的元素,结果是false。

lists:member([24,[1,24]]):检测24是否是列表中的元素,结果是true。

lists:nth(2,[3,4,10,7,9]):从列表中找到第二个元素。

6.7.2.length函数是内置函数:length([1,2,3])。

6.7.3.用于列表的操作符有3个:[...|...]构造器操作符(用来构造列表),++操作符(用来把两个列表相连组成了一个列表),--操作符(将右边列表中的每个元素从左边的列表中减去,如果右边的列表中的元素在左边的列表中找不到,那么它们就会被忽略掉);++操作符和--操作符的运算顺序是右结合的。

6.7.4.列表前添加元素:

方法一:直接使用构造器,例如[1|[2,3,4]]

方法二:使用++运算符,例如[1]++[2,3,4]

这两种方法产生同样的结果,但++运算符效率更低,并可能导致程序运行时速度大幅度减慢,因此当想添加一个元素到一个列表头部的时候,应该尽量使用高效率的构造器方法[...|...]。

6.7.5.proplists模块中包含了和属性列表相关的函数,属性列表是有次序的列表,它的元素可以是带有标记的元组,其中的第一个元素是用来寻找和插入的键值,也可以是基元(比如blah),这其实是元组{blah,true}的一种简写方式。

Erlang终端:

1.打开方式:

1.1.unix终端:在unix终端中输入erl来打开Erl终端窗口。

1.2.window终端:单机开始菜单中的Erl运行图标来打开。

2.表达式结束方式:

在表达式的最后用英文句点(.)来终止。

3.退出终端:

输入q(),再加上英文句点(.)

数学运算符:

1.整数和浮点数的运算包括加减乘除。

2.整数的运算结果是整数,浮点数除法的情况除外,它的结果是一个浮点数。

3.+(一元操作符,数据类型针对整数|浮点数),-(一元操作符,数据类型针对整数|浮点数),*(乘法,数据针对整数|浮点数),/(浮点除法,数据针对整数|浮点数,但是这是浮点除法,所以就算是整数相除,得到的也是浮点数),

div(整数除法,数据针对整数),rem(整数取余,数据针对整数),+(加法,数据针对整数|浮点数),-(减法,数据针对整数|浮点数)

4.计算规则:左结合,一元运算符+和-拥有最高的优先级,其次是乘除和取余数操作,而加减的优先级别最低。

项元比较:

1.在Erlang中比较项元需要两个表达式,它们位于比较运算符的左右两边,该表达式的结果是基元true或者false。

2.等于(==)和不等于(/=)运算符忽略两边的具体数据类型,而只比较两边的值。

3.精确等于(=:=)和不精确等于运算符不仅比较双方的值,也比较它们的数据类型。

4.比较运算符:==等于;/=不等于;=:=精确等于;=/=不精确等于;=<小于或等于;<小于;>=大于或等于;>大于。

5.如果表达式是不同的数据类型,number<auto<reference<fun<port<pid<tuple<list<binary。

6.列表按照字典顺序排序,就像字典里面的词一样,第一个元素先比较,小的那个表明这个列表也较小;如果它们是相同的,则第二个元素将继续进行比较,如此下去。当其中一个列表先比较完了,那么它就是较小的列表,例如:{boo,hoo}<{adder,zebra,bee}返回false,{boo,hoo}<{boo,hoo,adder,zebra,bee}返回true。

7.元组比较时,会先比较结构中的元素数目,然后再一个个比较各个元素的值。

8.使用精确等于和不精确等于运算符可以提供给编译器和类型工具更多信息,并产生有效的代码,但是遗憾的是,=:=和=/=不是很漂亮简洁的运算符,它们常常使得代码变得丑陋。结果在编程中,包括许多Erlang运行时的系统程序中,经常使用等于和不等于运算符。

变量

1.变量是用来存储简单和复合数据类型的值。在Erlang中,变量必须以大写字母开头,后面的字符可以是大小写字母,整数和下划线。它们不能包含任何其它的"特殊"字符。

2.Erlang中的变量在一个变量的生命周期内,包括在Erlang终端处理过程中,只容许给变量赋值一次,这成为单次赋值,当你需要对一个变量的值进行计算和操作的时候,可以把结果存储在一个新的变量当中。

3.Erlang中的所有函数变量都是按值调用的:在函数被求值之前,所有的函数调用参数都已经被求值。在Erlang中不存在引用调用的概念。

4.Erlang的另一个有用的特性是我们不需要声明它们,只需要使用它们即可。Erlang中变量不需要事前声明的原因是因为它具有动态类型系统。根据在变量上能够进行的运算操作,在运行时在确定数据类型。

5.在使用变量之前,请牢记:变量只能被绑定一次。在终端中可以使用f()可以对所有的变量绑定进行解绑定,而f(variable)可以对具体变量variable解绑定,不过只能在终端中使用它们。

复杂数据结构

1.在Erlang中,复杂数据结构由不同的数据类型复合嵌套而成。这些数据结构可能包含绑定变量或者简单和复合的值。

模式匹配

1.Erlang的模式匹配可以用于:

变量赋值

控制程序的执行流程

从复合数据类型中提取值

2.模式匹配一般化的形式:Pattern=Expression,模式(Pattern)由绑定或者未绑定的变量以及字符量(比如基元,整数或者字符串)所组成。一个绑定的变量是一个已经绑定值的变量,未绑定的变量是指一个尚未绑定值的变量;表达式Expression可以包含数据结构,绑定变量,数学运算和函数调用,它不能包含未绑定的值。

3.模式匹配产生的结果:

模式匹配成功,然后未绑定的变量因而变成绑定的变量了。

模式匹配失败,结果是没有绑定值。

4.模式匹配成功与否决定因素,先计算=运算符右边的Expression,然后把它的值跟Pattern去比较:

表达式和模式必须有相同的形式:有三个元素的一个元组只可以匹配有三个元素的一个元组,一个列表[X|Xs]只可以匹配一个非空的列表。

模式中的常量必须跟表达式相同位置上的值相等。

如果模式匹配成功,会把未绑定的变量绑定到相应的表达式的值上。

绑定变量的值必须和表达式相应位置上的值相等。

5.变量可以用下划线开始,下划线是一个特殊的标记,它告诉编译器,这些变量是无关紧要的,它们只是作为程序中不需要的变量的占位符,“无关紧要”的变量的功能跟普通变量一样,可以检查、使用和比较它们的值。唯一不同的是,普通变量的值如果从未使用过,编译器将会发出警告,而使用“无关紧要的”变量则不会,使用“无关紧要的”变量是一种很好的编程实践,这告诉阅读代码的人应该忽略到这个值。为了提高可读性和维护性,程序员经常以“无关紧要”变量的形式引入值和类型,下划线本身也是一个“无关紧要的”变量,但不能访问其内容,因为它的值被忽略了而且从未被绑定。例如{A,_,[B|_],{B}}={abc,23,{22,23},{22}},这个是正确的,因为下划线不能被绑定;{A,_int,[B|_int],{B}}={abc,23,[22,23],{22}}这个是错误的,因为_int是一个变量,它被赋予了值23,而[B|_int]中的_int是一个列表,所以这个是不正确的。

函数

函数的名称是一个基元。一个函数的头包括名字,随后是一对括号,在里面包含多个形式的参数或者没有参数,在Erlang中,函数参数的数量叫做元数,使用箭头(->)来分割函数头和函数主体。

模块

1.函数组合在一起构成了模块,一个程序往往分散在几个模块当中,每个模块包括按逻辑组合在一起的函数。模块文件以.erl后缀来结尾,文件名称和模块名称必须是相同的,模块可以这样直接命名-module(Name)。

2.export指令以Function/Arity的格式,包含了导出函数的一个列表。这些函数是全局性的,这意味着可以从模块的外部调用它们,在Erlang中,注释以百分比(%)开始直到该行结束。

3.全局调用,也称为完全限定的函数调用,是在函数前加上模块名字作为前缀来实现的。例如demo:double(2),局部函数只可以在模块内部使用。

4.Erlang的函数由它们的名字,元数和定义所在的模块唯一标示的。两个函数在同一个模块中可能有相同的名字,却有不同的元数。如果是这样,它们就是不同的函数,并且相互之间没有关系,只要函数是在模块中定义的,那么就没有必要在调用之前声明它们。

Erlang的编译和虚拟机

1.若要执行从一个模块中导出的函数,你必须编译代码,这会在模块相同的目录下面生成一个module.beam文件:

如果你使用的是unix操作系统,请在源代码目录下面打开Erlang终端。

在Windows环境下,一种打开werl终端的方法是右击一个.beam文件,然后从弹出的窗口菜单中选择Open With Option的"werl"选项。从现在起,双击任何源文件相同目录下的.beam文件,就会打开一个Erlang终端。

2.在这两种操作系统下,你可以使用Erlang终端中使用cd(directory)进入到各个目录。一旦进入该目录,你就可以在Erlang的终端中使用c(Module)并省略名称中的.erl后缀来进行编译,如果代码中没有错误,则会编译成功。

3.大型的Erlang系统一般由多个松散耦合的Erlang模块组成,它们都在独立的基础上各自编译。一旦你编译了代码,在源代码目录下面我们找到一个与模块名称相同的文件,但以后缀.beam结尾,这个文件包含了你可以从其他任何函数调用的字节代码。后缀.beam指的是Erlang抽象虚拟机,它是一个可以运行编译代码的抽象虚拟机。

4.一旦编译成功,你就可以使用完全限定名称来调用这些函数了,这是因为你是从模块外部调用这些函数的,

模块指令

每个模块都拥有一个-attribute(Value)格式的属性列表,它们通常放在模块的开始,是由放在属性前面的-符号和结尾的句点来定义。module属性是强制性的,它定义了模块的名称;export([函数/元素])定义了导出的函数列表;-compile(export_all)指令,它会在编译阶段导出模块中的所有函数,另一个方法是在编译这个文件时加上特定的选项c(Mod,[export_all]),这个指令只用于测试目的,在代码被添加到产品的时候,要使用export指令代替它;-import(Module,[Function/Arity,...]),它允许你从其它模块中导入它们,然后本地调用它们;你可以编写自己的模块属性,常见的例子包括:-author(Name)和date(Date),用户定义的属性只能有一个参数;所有的属性和模块的其他信息可以通过Mod:module_info/0或者选择性调用Mod:module_info/1函数得到。

猜你喜欢

转载自yansxjl.iteye.com/blog/2356970