ErLang 入门

来源:互联网 发布:淘宝美的官方旗舰店 编辑:程序博客网 时间:2024/09/21 09:22

文章来自 http://learnxinyminutes.com/docs/files/erlang-cn.erl

% 百分比符号标明注释的开始。%% 两个符号通常用于注释函数。%%% 三个符号通常用于注释模块。% Erlang 里使用三种标点符号:% 逗号 (`,`) 分隔函数调用中的参数、数据构建和模式。% 句号 (`.`) (后跟空格)分隔函数和 shell 中的表达式。% 分号 (`;`) 分隔语句。以下环境中使用语句:% 函数定义和`case`、`if`、`try..catch`、`receive`表达式。%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1. 变量和模式匹配%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Num = 42.  % 变量必须以大写字母开头。% Erlang 的变量只能赋值一次。如果给变量赋不同的值,会导致错误:Num = 43. % ** exception error: no match of right hand side value 43% 大多数语言中`=`表示赋值语句,在Erlang中,则表示模式匹配。% `Lhs = Rhs`实际上意味着:% 演算右边(Rhs), 将结果与左边的模式匹配。Num = 7 * 6.% 浮点数Pi = 3.14159.% Atoms 用于表示非数字的常量。% Atom 以小写字母开始,包含字母、数字、`_`和`@`。Hello = hello.OtherNode = example@node.% Atom 中如果包含特殊字符,可以用单引号括起。AtomWithSpace = 'some atom with space'.% Erlang 的元组类似 C 的 struct.Point = {point, 10, 45}.% 使用模式匹配操作符`=`获取元组的值。{point, X, Y} = Point.  % X = 10, Y = 45% 我们可以使用`_`存放我们不感兴趣的变量。% `_`被称为匿名变量。和其他变量不同,% 同一个模式中的多个`_`变量不必绑定到相同的值。Person = {person, {name, {first, joe}, {last, armstrong}}, {footsize, 42}}.{_, {_, {_, Who}, _}, _} = Person.  % Who = joe% 列表使用方括号,元素间使用逗号分隔。% 列表的元素可以是任意类型。% 列表的第一个元素称为列表的 head,其余元素称为列表的 tail。ThingsToBuy = [{apples, 10}, {pears, 6}, {milk, 3}].% 若`T`是一个列表,那么`[H|T]`同样是一个列表,head为`H`,tail为`T`.% `|`分隔列表的 head 和 tail.% `[]`是空列表。% 我们可以使用模式匹配操作来抽取列表中的元素。% 如果我们有一个非空的列表`L`,那么`[X|Y] = L`则% 抽取 L 的 head 至 X,tail 至 YXY需为未定义的变量)。[FirstThing|OtherThingsToBuy] = ThingsToBuy.% FirstThing = {apples, 10}% OtherThingsToBuy = {pears, 6}, {milk, 3}% Erlang 中的字符串其实是由整数组成的数组。字符串使用双引号。Name = "Hello".[72, 101, 108, 108, 111] = "Hello".%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2. 循序编程%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ModuleErlang 代码的基本单位。我们编写的所有函数都储存在 module 中。% Module 存储在后缀为 `.erl` 的文件中。% Module 必须事先编译。编译好的 module 以 `.beam` 结尾。-module(geometry).-export([area/1]). % module 对外暴露的函数列表% `area`函数包含两个分句,分句间以分号相隔。% 最后一个分句以句号加换行结尾。% 每个分句由头、体两部门组成。% 头部包含函数名称和用括号括起的模式,% 体部包含一系列表达式,如果头部的模式和调用时的参数匹配,这些表达式会被演算。% 模式匹配依照定义时的顺序依次进行。area({rectangle, Width, Ht}) -> Width * Ht;area({circle, R})            -> 3.14159 * R * R.% 编译文件为 geometry.erl.c(geometry).  % {ok,geometry}% 调用函数时必须使用 module 名和函数名。geometry:area({rectangle, 10, 5}).  % 50geometry:area({circle, 1.4}).  % 6.15752% 在 Erlang 中,同一模块中,参数数目不同,名字相同的函数是完全不同的函数。-module(lib_misc).-export([sum/1]). % 对外暴露的`sum`函数接受一个参数:由整数组成的列表。sum(L) -> sum(L, 0).sum([], N)    -> N;sum([H|T], N) -> sum(T, H+N).% fun 是匿名函数。它们没有名字,不过可以赋值给变量。Double = fun(X) -> 2*X end. % `Double` 指向匿名函数 #Fun<erl_eval.6.17052888>Double(2).  % 4% fun 可以作为函数的参数和返回值。Mult = fun(Times) -> ( fun(X) -> X * Times end ) end.Triple = Mult(3).Triple(5).  % 15% 列表解析是创建列表的表达式(不使用fun、map 或 filter)。% `[F(X) || X <- L]` 表示 "由 `F(X)` 组成的列表,其中 `X` 取自列表 `L`。L = [1,2,3,4,5].[2*X || X <- L].  % [2,4,6,8,10]% 列表解析可以使用生成器,也可以使用过滤器,过滤器用于筛选列表的一部分。EvenNumbers = [N || N <- [1, 2, 3, 4], N rem 2 == 0]. % [2, 4]% Guard 是用于增强模式匹配的结构。% Guard 可用于简单的测试和比较。% Guard 可用于函数定义的头部,以`when`关键字开头,或者其他可以使用表达式的地方。max(X, Y) when X > Y -> X;max(X, Y) -> Y.% guard 可以由一系列 guard 表达式组成,这些表达式以逗号分隔。% `GuardExpr1, GuardExpr2, ..., GuardExprN` 为真,当且仅当每个 guard 表达式均为真。is_cat(A) when is_atom(A), A =:= cat -> true;is_cat(A) -> false.is_dog(A) when is_atom(A), A =:= dog -> true;is_dog(A) -> false.% guard 序列 `G1; G2; ...; Gn` 为真,当且仅当其中任意一个 guard 表达式为真。is_pet(A) when is_dog(A); is_cat(A) -> true;is_pet(A) -> false.% Record 可以将元组中的元素绑定到特定的名称。% Record 定义可以包含在 Erlang 源代码中,也可以放在后缀为`.hrl`的文件中(Erlang 源代码中 include 这些文件)。-record(todo, {  status = reminder,  % Default value  who = joe,  text}).% 在定义某个 record 之前,我们需要在 shell 中导入 record 的定义。% 我们可以使用 shell 函数`rr` (read records 的简称)。rr("records.hrl").  % [todo]% 创建和更新 record。X = #todo{}.% #todo{status = reminder, who = joe, text = undefined}X1 = #todo{status = urgent, text = "Fix errata in book"}.% #todo{status = urgent, who = joe, text = "Fix errata in book"}X2 = X1#todo{status = done}.% #todo{status = done,who = joe,text = "Fix errata in book"}% `case` 表达式。% `filter` 返回由列表`L`中所有满足`P(x)`为真的元素`X`组成的列表。filter(P, [H|T]) ->  case P(H) of    true -> [H|filter(P, T)];    false -> filter(P, T)  end;filter(P, []) -> [].filter(fun(X) -> X rem 2 == 0 end, [1, 2, 3, 4]). % [2, 4]% `if` 表达式。max(X, Y) ->  if    X > Y -> X;    X < Y -> Y;    true -> nil;  end.% 警告: `if` 表达式里至少有一个 guard 为真,否则会触发异常。%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3. 异常%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 当遇到内部错误或显式调用时,会触发异常。% 显式调用包括 `throw(Exception)`, `exit(Exception)` 和% `erlang:error(Exception)`.generate_exception(1) -> a;generate_exception(2) -> throw(a);generate_exception(3) -> exit(a);generate_exception(4) -> {'EXIT', a};generate_exception(5) -> erlang:error(a).% Erlang 有两种捕获异常的方法。其一是将调用包裹在`try...catch`表达式中。catcher(N) ->  try generate_exception(N) of    Val -> {N, normal, Val}  catch    throw:X -> {N, caught, thrown, X};    exit:X -> {N, caught, exited, X};    error:X -> {N, caught, error, X}  end.% 另一种方式是将调用包裹在`catch`表达式中。% 此时异常会被转化为一个描述错误的元组。catcher(N) -> catch generate_exception(N).%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 4. 并发%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Erlang 依赖于 actor并发模型。在 Erlang 编写并发程序的三要素:% 创建进程,发送消息,接收消息% 启动一个新的进程使用`spawn`函数,接收一个函数作为参数F = fun() -> 2 + 2 end. % #Fun<erl_eval.20.67289768>spawn(F). % <0.44.0>% `spawn` 函数返回一个pid(进程标识符),你可以使用pid向进程发送消息。% 使用 `!` 操作符发送消息。%  我们需要在进程内接收消息,要用到 `receive` 机制。-module(caculateGeometry).-compile(export_all).caculateAera() ->    receive      {rectangle, W, H} ->        W * H;      {circle, R} ->        3.14 * R * R;      _ ->        io:format("We can only caculate area of rectangles or circles.")    end.% 编译这个模块,在 shell 中创建一个进程,并执行 `caculateArea` 函数。c(caculateGeometry).CaculateAera = spawn(caculateGeometry, caculateAera, []).CaculateAera ! {circle, 2}. % 12.56000000000000049738% shell也是一个进程(process), 你可以使用`self`获取当前 pidself(). % <0.41.0>
0 0
原创粉丝点击