您的位置:首页 > 理论基础 > 数据结构算法

erlang语言的基础概念知识

2017-03-29 00:00 337 查看
相信很多朋友都知道,erlang的强大和高效。那么接下来分析一下erlang的一些简单的基础知识。

启动和退出shell:

首先,从启动erlang shell说起,启动shell,只需在vim编辑器中运行erl命令,就能成功启动shell。如下图所示:



当看到这种代码时,就意味着shell已经成功开启。不过在输入表达式时一定要以英文状态下的句号(.)结尾;同时需要了解shell只会保留最近20条求值结果;退出shell需要使用q().或者halt().命令,同样的也需要以英文状态下的句号结尾。如下图:



看到这些代码就证明已经成功退出了shell。q().命令是退出当前shell进程;halt().命令是结束所有进程。区别还是很大的。

数据类型及运算:

erlang数据类型有:数值、二进制串/位串、原子、元组、列表(和字符串)、唯一标识(pid、端口、引用)、Fun函数。erlang中的数据通常被称作项式。erlang的数值运算在必要的时候会自动将整型转换成浮点型。比如除法运算,在erlang编程中除法运算得到结果都是浮点型。想得到整型可以使用整除命令div——4 div 2,得到结果为2。

二进制串就是无符号8位字节的序列,用于存放和处理数据块;位串是广义的二进制串,长度不必是8位的整数倍。

原子是一种仅由字符序列来标识的特殊字符串常量。Erlang中原子作为标签,无需事先声明,可以随意创建并随处使用各个新的原子。Erlang中常用的原子:true/false用于布尔运算、ok用于那些返回值没有实际意义,仅通过副作用发挥作用的函数、undefined用作标识未知量的占位符。

Erlang的一个标准约定:用原子作为第一个元素来标记元组数据的类型。称为标记元组。元组的元素项没有名称,只有编号。注意:元组针对的是定长序列。要处理边长序列,需要用列表。

列表天然遵循引用透明性——其基本思想是被名称所引用的值不可更改。Erlang的单次赋值造就了引用透明性。列表添加元素[1 | []] |左侧是要添加的元素,左侧也可是多个元素。也可用++ [1,2] ++ [3,4] 左侧列表的长度决定了++运算符的耗时。

Erlang中的双引号字符串就是列表,其元素就是该字符串中的各字符的数值编码所对应的整数。所有处理列表的方法都可以对字符串使用。

Erlang被称为函数式语言,可以像处理数据一样处理函数。函数可以称为别的函数的输入,也可以是别的函数的求值结果,还可以把函数存在数据结构中供后续调用。这种将函数包装成数据的对象称为fun函数。

项式的比较:

erlang中的项式比较:数值小于原子、元组小于列表、原子即小于元组也小于列表(字符串也是列表)。

任意两个项式都可以比较,结果总是确定的。比较运算符看起来绝对不能像箭头!小于或等于号=< 大于或等于>= 相等比较=:= 不完全相等=/=

看似相等的整数和浮点数被判为不相等 2 =:= 2.0 结果为false。按数学法则对数值进行比较时,应该改用算术相等运算符==,否定式写作/=。针对浮点数的判断总是会有些微小的舍入误差,涉及浮点时最后使用<,>,=<,>=进行比较。

==的正确性是得不到保障的,除了算术运算意外,它基本上总有问题。

解读列表:

列表一般是由空表和所谓的列表单元共同构成,这些单元各自携带一个元素挨个儿挂接到现有的列表的顶部,从而在内存中星城一个单链表。列表主要存放临时数据、编排中间结果、或是用作字符串缓冲。

列表分为严格列表和非严格列表。 严格列表的尾部是以一个空表结尾。非严格列表结尾不是以空表结尾,而且是堆叠列表单元而成的列表。 很多函数要求输入参数必须是严格列表,而非严格列表在函数遍历列表时不是以正常的空表结尾,就会导致崩溃(或者抛出异常)。

变量:

赋值之后,变量没有被使用时,往往会触发编译警告,如果仅仅是为了提高程序可读性,可以在变量名前加上下划线,编译器不会报警,同时未被使用的变量还会被优化掉,不会带来额外的成本。

Erlang的变量被严格的限定只能接受单次赋值。

Erlang中的所有副作用都可被视作消息。

函数子句、保护式与表达式:

子句保护式由关键字when开始到->箭头结束,其中可以包含一个或多个由逗号分隔的判定,仅当所有判定都为true时该子句才会被选中。

包括此类类型判定在内,能用在保护式中的操作十分有限,大部分运算符都可以用(+,-,*,/,++等),部分内置函数也可以用(self()),但是不能调用自定义的函数或其他模块中的函数。原因:①效率——子句选择必须足够快;②这些函数可能带有副作用。erlang中的副作用都可被视作消息。

Erlang的变量是无需声明的,按需取用即可。但是要求同一子句内的变量不能重名。

if表达式时case表达式的一种缩略形式,它不针对特定的值做分之判断也不含模式。

匿名fun函数要发挥作用,就必须与变量绑定,或者作为参数被传给其他函数。本地fun函数短暂的有效期,不适合长期保存,若是将它们以消息的形式发给别的erlang系统,则接收方必须持有相同版本的代码才能顺利调用这些fun函数,这种情况应该使用远程别名。

异常:

异常到底是什么?你可以将之认为是函数的另一种返回形式,区别在于它不仅会返回至调用者,还会返回到调用者的调用者,并一路向上,直至被捕获或抵达进程调用的起点。异常分为三类:error、exit、throw。

throw和exit都是常用函数,因此会被自动导入;调用时无须加erlang:前缀。

catch...end之间子句的模式有些特殊——它们可以用冒号作为异常的类别和被抛出的项式的分隔符。如果省略类别,默认为throw。

需要注意的是: 一旦进入catch部分,代码就不再受到保护了,catch子句中抛出的新的异常,会传播到try表达式之外!

当需要区分正常情况和异常情况并做出不同的处理时,可以使用try的复杂形势。

可以给任意try表达式加上一个after段,其作用在于确保某段具有副作用的代码的执行。

栈轨迹是异常发生那一刻位于栈的顶部的那些调用的逆序列表(最后一个调用位于列表最前)。

对于throw,得到的结果就是被抛弃的项式;对于exit,得到的是包含退出原因的标记元组;而对于error,得到的是一个包含异常本身和栈轨迹的标记元组。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  erlang 数据结构 异常