您的足迹: Erlang学习世界

Erlang学习世界

Erlang学习世界

学习Erlang的理由

  1. 希望编写能在多核计算机上运行更快的程序
  2. 希望编写不停机即可修改的可容错性程序
  3. 希望尝试传说中的“函数式语言”的魅力
  4. 希望使用一种语言,它既在大规模工业产品中经过实践检验,又不乏优秀的类库与活跃的社区
  5. 不希望在冗长烦琐的代码中耗费时间
  6. Erlang没有可变状态,也就没有共享内存,更没有锁,这一切都有利于并行化程序的编写和执行

Erlang程序可以由几百万个超轻量级的进程组成。这些进程可以运行在单处理器,多核处理器或处理器网络中。

Erlang的语法记要

  • 百分号(%)表示注释的开始
  • . 表示表达式的完成
  • Erlang采用不定长的整数来进行整数的算术演算。因此,不用担心运算溢出。
  • f()可以释放所有绑定的变量。执行这个命令后,所有的变量都变成了自由变量。
  • 在Erlang中,同一个模块的两个函数,如果同名但不同目(参数),则这两个函数被认为是不相同的。
  • @spec 是Erlang类型文档标记。常用这个标记在文档中描述函数的参数及其返回类型。
  • module 和 function名字都必须是小写
  • 变量必须以大写字母开头
  • Erlang 中只有public和private的函数,public的函数是指export出去的,其他的是private的
  • 一个函数的声明是名字加上参数个数,例如start/1,stop/0
  • 在模式匹配时,下划线(_) 表示匿名变量,可以匹配任何值
  • 用$ 加字符可以取得相对应的ascii码,如$a = 97.

变量

  • 变量必须以大写字母开头
  • 变量是单一赋值变量,只能一次性的给定。含有一个被赋予的值,则被称为绑定变量,否则,则为自由变量
  • =是一个模式匹配运算符当X是一个自由变量时,它的行为与赋值一致,换之,则为模式匹配。

原子

  • 原子用来表示不同的非数字常量值,类似于全局变量,无需使用宏定义或者包含文件即可使用。
  • 原子必须以小写字母开头,后跟数字字母或下划线,邮件符。使用单引号引起来的字符也是原子。原子的值就是原子自身

元组

  • 将若干个逗号(,)分割的值用花括号{}引起来,就形成了一个元组(tuple)。用来表示由多个项形成单一的实体,类似于C中的结构体。
  • 创建元组
Name = {name,joe}.
Age = {age,20}.
Person = {person,Name,Age}.
 
=> {person,{name,joe},{age,20}}
  • 提取元组中的字段值 <code erlang> {person,{_,Who},Age} = Person.

Who. ⇒ jo </code> 为占位符,表示那些我们不关心的变量。与常规常量不同,在同一模式中的不同地方,各个所绑定的值不必相同

列表

  • 将若干个以逗号(,)分割的值用一对方括号[]括起来,就形成了一个列表,用于存储数目可变的东西。
List = [Name,Age].
 
=> [{name,joe},{age,20}]

注意,列表的头可以是任何东西,但是列表的尾通常还是一个列表

  • 从列表中提取元素
[N|Last] = List.
 
N.
=> {name,joe}

字符串

  • 严格地讲,erlang中没有字符串,字符串实际上是一个整数列表。用双引号“”将一串字符括起来就是一个字符串,在erlang中,必须使用双引号
  • shell打印一串列表值时,如果列表中的所有整数全部都是可打印字符,则把列表当字符串来打印。
[83,117,114,112,114,105,115,101].
=> "Surprise"
 
[1,83,117,114,112,114,105,115,101].
=> [1,83,117,114,112,114,105,115,101].  <- 其中包括一个“1”不是可打印字符

标点符号

在Erlang中会使用三种标点符号

逗号(,)

用来分隔函数调用,数据构造器以及模式中的参数

分号(;)

用来分隔子句: 分段的函数定义,case语句,if语句,try...cacth语句以及receive表达式

句号(.)

用来在shell中分隔完整的函数和表达式

匿名函数

fun就匿名函数,以end结束

28> Temp = fun({c,C})->{f,32+C*9/5};
28> ({f,F})->{c,(F-32)*5/9} end.
#Fun<erl_eval.6.13229925>
 
29> Temp({c,100}).
{f,212.0}
 
30> Temp({f,212}).
{c,100.0}

列表处理

-module(shop2).
-export([total/1]).
-import(lists,[map/2,sum/1]).
-import(shop,[cost/1]).
 
total(L)->
         sum(L).

列表解析

记号[ F(X) || X ← L ]代表“由F(X)组成的列表,其中X值来自于列表L”

例一: 求列表中各自数字的平方

List = [1,2,3,4].
[ X*X || X <- List].
 
=> [1,4,9,16].

例二: 计算水果的各自总价

Fruits=[{orange,4},{apples,5},{milk,4}].
 
[shop:cost(What)*N || {What,N} <- Fruits ].
 
=> [20,10,28]

例三: 把元组的数量乘2

Fruits = [{orange,4},{apples,5},{milk,4}].
[{What,N*2} || {What,N} <- Fruits ].
 
=> [{orange,8},{apples,10},{milk,8}]

列表快速排序

-module(lib_misc).
-export([qsort/1]).
 
qsort([])->[];
qsort([Pivot|T])->
                 qsort([X || X<-T,X<Pivot])
                 ++ [Pivot] ++
                 qsort([X || X<-T,X>=Pivot]).

列表分离元素

X–Y是列表的分离操作符,它从列表X中分离出元素Y

List=[1,2,3,4].
List -- [2,3].
 
=> [1,4]

记录

记录是一种把一个名称和元组中的一个元素对应起来的方法。语法:

-record( Name, {
                key1 = value1,
                key2 = value2,
                key3,
                }
).

Name,key1,key2..等是记录中的字段名,这些名字必须是原子(全部小写)。记录中的每个字段都可以有默认值。如果在记录创建的时候,如果没有指定值,则使用默认值。

定义记录文档 : records.hrl

-record(todo,{status=reminder,who=joe,text}).

读取记录

1> rr("records.hrl").

创建和更新记录

X=#todo{}.
 
X1=#todo{status=urgent,text="Fix error in book"}.
 
X2=X1#todo{status=done}.

获取记录字段

#todo{who=W,text=Text} = X2.
 
or 
 
X2#todo.text.

BIF内建函数

BIF (Build-in function),顾名思义就是Erlang中的内置函数。它们通常用来实现完成那些无法用Erlang完成的任务。如,将列表转换成元组或者获取当前的时间和日期。

1> tuple_to_list({12,cat,"Hello"}).
[12,cat,"Hello"]
 
2> time().
{20,0,3}

所有的BIF都在Erlang模块之中,而且大部分常用的BIF都已经被自动导入,因此,我们调用的时候只要写直接的函数名即可。

二进制数据

在Erlang中可以使用一种二进制(binary)数据的结构来存储大量的原始数据。相对于元组和列表,二进制类型更加节省内存,而且运行时系统也对此进行了优化,对二进制数据的输入输出会更加高效。

如:

1> <<5,10,20>>.
<<5,10,20>>
 
2> <<"hello">>.
<<"hello">>
 
3> <<99,97,116>>.
<<"cat">>

在二进制数据中使用的整数,每一个都必须要在0和255之间,如果超出255,将显示为0。
由字符序组成的二进制数据等同于由其每一个字符的ASCII编码组成的二进制数据,即«99,97,116» 等同于 «“cat”»

wiki/public/进入erlang的世界吧.txt · 最后更改: 2025/11/22 03:57