最简练的Erlang根底
0x00 说在前面
Erlang读音/ˈɜːrlæŋ/
。第一次见到的时分总感觉怎样读都读不对,后来在维基上看到Erlang标示了音标,才干精确的读出来,并且也没那么奇怪。由于作业才有时机触摸这门言语,也因而只要三天的时刻能够看《Erlang程序设计》这本书。学习这门言语的时分带着一个作业方针:把一个Erlang日志搜集剖析核算的代码转换成Python的。而Erlang的风格是尽量不写注释,尽量在写函数名和变量名的时分表达清楚代码的意义。这样一来学习Erlang就成了必要的,很幸亏,领导给了三地利刻学习,三地利刻根本也足够了。除了这一片根底语法的入门篇之外,后续还有一篇或许两篇并发编程和分布式编程的,究竟这个才是Erlang拿手的范畴。话不多说,show me your article
0x01 装备开发环境
依靠东西:
- Erlang版别:18.3
- IDE:IDEA
下载链接:
- Erlang:https://www.erlang.org/downloads 挑选otp18.3即可。
- IDEA:https://www.jetbrains.com/idea/download 挑选社区版即可。
IDEA装备Erlang插件:
- IDEA官方文档-运用IDEA开发Erlang
0x02 根底知识
注释
- % 百分比符号标明注释的开端。
- %% 两个符号一般用于注释函数。
- %%% 三个符号一般用于注释模块。
变量
一切的变量都有必要以大写字母最初,变量只可一次赋值,赋值之后不可在变。 f()函数开释shell绑定变量。
浮点数
- 浮点数有必要含有小数点且小数点后有必要有一位10进制数
- 用/来除两个整数时相除成果会主动转换成浮点数
- div取整,rem取余
三种标点符号
- 整个函数的界说结束时用一个句号“.”
- 函数参数,数据构建,次序句子之间,用逗号“,”分隔
- 函数界说、
case
、if
、try..catch
、receive
表达式中的方式匹配时,用分号“;”分界
恒等
恒等测验符号 =:=以及不等测验符号 =/=
块表达式
当程序中某处的语法要求只能运用单个表达式可是逻辑上又需求在此运用多个表达式时,就能够运用begin...end快表达式
begin
Expr1,
...
ExprN
end
0x03 内置数据结构
元组及方式匹配(解构)
- _ 代表丢掉的变量,和python相同
- 匹配时方式匹配符=左右两头的元组的结构有必要相同。
1> Point = {point, 20, 43}.
{point,20,43}
2> {point, x, y} = Point.
** exception error: no match of right hand side value {point,20,43}
3> {point, X, Y} = Point.
{point,20,43}
4> X.
20
5> Y.
43
6> Person = {person, {name, {first, joe}, {last, armstrong}}, {footsize, 42}}.
{person,{name,{first,joe},{last,armstrong}},{footsize,42}}
7> {_, {_, {_, Who}, {_, _}}, {_, Size}} = Person.
{person,{name,{first,joe},{last,armstrong}},{footsize,42}}
8> Who.
joe
9> Size.
42
列表
- 列表元素能够是不同的类型。
- 列表头:列表的第一个元素
- 列表尾:列表除第一个元素剩余的部分
- 竖线符号|
- 将列表的头和尾切割开来
- [E1, E2, E4, ... , |L]:运用|向列表L的开始处参加多个元素构形成新的列表
- 列表链接操作符 ++ (中缀添加操作符)
列表操作演示代码
1> L = [1+7, hello, 2-2, {cost, apple, 30-20}, 3].
[8,hello,0,{cost,apple,10},3]
2> L1 = [123, {oranges, 4} | L].
[123,{oranges,4},8,hello,0,{cost,apple,10},3]
3> [E1 | L2] = L1.
[123,{oranges,4},8,hello,0,{cost,apple,10},3]
4> E1.
123
5> L2.
[{oranges,4},8,hello,0,{cost,apple,10},3]
6> [E2, E3 | L3] = L2.
[{oranges,4},8,hello,0,{cost,apple,10},3]
7> E3.
8
列表表达式
方式:[F(X) || X <- L]
1> L = [1, 2, 3, 4, 5].
[1,2,3,4,5]
2> [2 * X || X <- L].
[2,4,6,8,10]
3> [X || {a, X} <- [{a, 1}, {b, 2}, {c, 3}, {a, 4}, hello, "wow"]].
[1,4]
字符串
Erlang的字符串是一个整数列表。整数列表的内容由每一个字符对应的ascii码构成
1> I = $s.
115
2> [I-32, $u, $r, $p, $r, $i, $s, $e].
"Surprise"
3> $r.
114
4> [I-32, $u, $r, $p, 114, $i, $s, $e].
"Surprise"
映射组(Map)
映射组是一个由多个Key-Vaule结构组成的契合数据类型,类似于Python的字典。详细运用如下
1> M1 = #{"name" => "alicdn", "percentage" => 80}.
#{"name" => "alicdn","percentage" => 80}
2> maps:get("name", M1).
"alicdn"
3> M2 = maps:update("percentage", 50, M1).
#{"name" => "alicdn","percentage" => 50}
4> map_size(M1).
2
5> #{"name" := X, "percentage" := Y} = M2.
#{"name" => "alicdn","percentage" => 50}
6> X.
"alicdn"
7> Y.
50
结构映射组和方式匹配时的符号不一样,=>
和:=
的差异。常见的put办法拜见erlang maps库的运用。
0x04 模块
- 一个模块存放于一个.erl文件中(模块名和文件名相同)
- 编译模块的指令:c(模块名)。编译成功之后就会加载到当时shell中
- 调用模块中的函数:模块名:函数名(参数)
- 导入模块中的函数:
-import(lists, [map/2, sum/1]).
- 导出模块中的函数:
- 导出指定函数
-export([start/0, area/2]).
- 导出悉数函数
-compile(export_all).
,防止在开发阶段经常会向export中添加函数或许删去函数
- 导出指定函数
-module(learn_test).
-author("ChenLiang").
%% API
-export([area/1]).
area({rectangle, Width, Height}) -> Width * Height;
area({circle, R}) -> 3.14159 * R * R;
area({square, X}) -> X * X.
编译模块,调用函数
1> c(learn_test).
{ok,learn_test}
2> learn_test:area({circle, 2.0}).
12.56636
3>
0x05 函数
根本函数
同名同目(参数数量,arity)的才是同一个函数。因而函数名相同,目不相同的函数是彻底不同的两个函数。同名不同意图函数一般作为辅佐函数。
-
函数不会显现地回来值,函数中最终一条句子的履行成果将作为函数的回来值。
-
同一个函数中,并排的逻辑分支之间,用分号 “;” 分界;次序句子之间,用逗号 “,” 分隔。
示例代码:核算列表元素的和
-module(learn_test).
-author("ChenLiang").
%% API
-export([sum/1]).
sum(L) -> sum(L, 0).
sum([], N) -> N;
sum([H|T], N) -> sum(T, H + N).
匿名函数
erlang中的匿名函数便是fun。fun也能够有若干个不同的字句。
1> Z = fun(X) -> 2*X end.
#Fun<erl_eval.6.50752066>
2> Double = Z.
#Fun<erl_eval.6.50752066>
3> Double(4).
8
4> TempConvert = fun({c, C}) -> {f, 32 + C * 9 / 5};
5> ({f, F}) -> {c, (F - 32) * 5 / 9}
6> end.
#Fun<erl_eval.6.50752066>
7> TempConvert({c, 100}).
{f,212.0}
8> TempConvert({f, 212}).
{c,100.0}
高阶函数
回来fun或许承受fun作为参数的函数都称为高阶函数。
以fun为参数的函数
常见的是lists模块中的map(Fun, List1) -> List2,filter(Pred, List1) -> List2函数。
lists模块的详细运用拜见:https://www.erlang.org/doc/man/lists.html
1> Even = fun(X) -> X rem 2 =:= 0 end.
#Fun<erl_eval.6.50752066>
2> lists:map(Even, [1, 2, 3, 4, 5, 6]).
[false,true,false,true,false,true]
3> lists:filter(Even, [1, 2, 3, 4, 5, 6]).
[2,4,6]
回来fun的函数
一般在回来的函数内部封装了一些变量和逻辑。一般情况下不写回来fun的函数。
1> Mult = fun(Times) -> (fun(X) -> X * Times end ) end.
#Fun<erl_eval.6.50752066>
2> Triple = Mult(3).
#Fun<erl_eval.6.50752066>
3> Triple(4).
12
0x06 断语
强化方式匹配的功用,给方式匹配添加一些变量测验和比较的才能
max(X, Y) when X > Y -> X;
max(_, Y) -> Y.
0x07 记载
记载是Erlang中根据元组的key-value数据界说,运用示例如下:
-module(learn_test).
-author("ChenLiang").
%% API
-export([record_test1/0, record_test2/0]).
-record(person, {name, age=18, hobby=["erlang"]}). %% record界说能够存放于hrl和erl中
record_test1() ->
Person = #person{name="hahaha"}, %% 为record中字段赋值
Person#person.hobby. %% 经过.操作符拜访record中字段
record_test2() ->
Person = #person{},
#person{name = Name} = Person, %% 经过方式匹配获取record字段
Name. %% 输出undefined
0x08 .hrl头文件
某些文件的扩展名为 .hrl
。这些.hrl
是在 .erl
文件中会用到的头文件,运用办法如下:
-include("File_Name").
例如:
-include("mess_interface.hrl").
.hrl 文件中能够包括任何合法的 Erlang 代码,可是一般里边只包括一些记载和宏的界说。
0x09 case / if 表达式
case 表达式
case句子语法
case Experssion of
Pattern1 [when Guard1] -> Expr_seq1;
Pattern2 [when Guard2] -> Expr_seq2;
...
end
将Expression的成果和各个Pattern逐一匹配,匹配成功,则核算表达式序列的值,并回来。悉数匹配不到,则直接报错。
case句子运用示例:
-module(learn_test).
-author("ChenLiang").
%% API
-export([filter/2]).
filter(P, [H|T]) ->
case P(H) of
true -> [H|filter(P, T)];
false -> filter(P, T)
end
;
filter(_, []) -> [].
在erl shell中运转成果如下:
1> c(learn_test).
{ok,learn_test}
2> learn_test:filter(fun(X) -> X rem 2 =:= 0 end, [1, 2, 3, 4, 5]).
[2,4]
if 表达式
if句子运用示例
-module(learn_test).
-author("ChenLiang").
%% API
-export([bigger/2]).
bigger(X, Y) ->
if
X > Y -> X;
X < Y -> Y;
true -> -1
end.
假如没有匹配的断语,则会抛出反常。因而最终一个断语一般是true断语。
0x10 反常
Erlang中一切都是表达式,都有回来值,因而反常捕获句子也有回来值。
捕获一切的反常_:_
-module(learn_test).
-author("ChenLiang").
%% API
-export([catch_exc1/0,catch_exc2/0]).
exception() ->
exit({system, "123123"}).
catch_exc1() ->
try
exception()
catch
_:_ -> 111
end.
catch_exc2() ->
try
exception()
catch
_ -> 222
end.
erl shell输出成果
1> learn_test:catch_exc1().
111
2> learn_test:catch_exc2().
** exception exit: {system,"123123"}
in function learn_test:exception/0 (learn_test.erl, line 17)
in call from learn_test:catch_exc2/0 (learn_test.erl, line 28)
多种过错的检测能够 运用try catch风格。
参阅stackoverflow-How do I elegantly check many conditions in Erlang?
记住帮我点赞哦!
精心整理了核算机各个方向的从入门、进阶、实战的视频课程和电子书,依照目录合理分类,总能找到你需求的学习材料,还在等什么?快去重视下载吧!!!
记忆犹新,必有回响,小伙伴们帮我点个赞吧,非常感谢。
我是职场亮哥,YY高档软件工程师、四年作业经验,回绝咸鱼争当龙头的斜杠程序员。
听我说,前进多,程序人生一把梭
假如有幸能帮到你,请帮我点个【赞】,给个重视,假如能顺带谈论给个鼓舞,将不胜感激。
职场亮哥文章列表:更多文章
自己一切文章、答复都与版权维护渠道有协作,著作权归职场亮哥一切,未经授权,转载必究!