函数与模块
模块是存放代码的地方
模块是Erlang的基本代码单元,保存在扩展名.erl
文件中,模块包含函数,可以顺序或并行运行。
geometry.erl -module(geometry) -export([area/1])
第一行是模块声明,模块名必须与存放改模块的文件名相同
第二行是导出声明,Name/
N带有N个参数的函数Name,N称为函数的元数
未从模块里导出的函数只能在模块内调用。(导出=》
公有,未导出=》
私有)
area({rectangle,Width,Height})->Width*Height; area({square,Side}) -> Side * Side.
子语句之间用;
隔开,句号和空白结果
子语句,头部和主体用 ->
隔开
头部包含一个函数,后接零个或多个模式,主体包含一列表达式,在头部模式与调用参数成功匹配时执行。
函数没有显示的返回语句,返回值就是字句主体里最后一条表达式的值。
代码测试
-module (geometry). -export ([test/0, area/1]). test() -> 12 = area({rectangle, 3, 4}), 144 = area({square, 12}), tests_worked. area({rectangle, Width, Height}) -> Width * Height; area({square, Side}) -> Side * Side. 1> c(geometry). {ok,geometry} 2> geometry:test(). tests_worked
扩展程序
加;继续扩展
符号
逗号,分隔函数调用,数据构造和模式中的参数
分号,分隔字句
句号,分隔函数整体,以及shell表达式
fun基本的抽象单元
函数式编程语言,表示函数可以作为其他函数的参数,也可以返回函数。操作其他函数的函数称为高阶函数。
-
对列表中每一个元素执行相同的操作,
list:map/2
和list:filter/1
-
创建自己的控制抽象。Erlang没有for循环,可以创建for循环
-
实现可重入解析代码、解析组合器或惰性求值器。
Double = fun(X) -> 2*X end.
计算直角三角形的斜边
Hypot = fun(X,Y) -> math:sqrt(X*X + Y*Y) end.
fun可以有不同的字句
TempConvert = fun({c, C}) -> {f, 32 + C*9/5};
fun({f, F}) ->{c, (F-32)*5/9}
end.
以fun作为参数的函数
Even=fun(X) -> (X rem 2) =:= 0 end.
lists:map(Even,[1,2,3,4,5,6,7,8]).
lists:filter(Even,[1,2,3,4,5,6,7,8]).
[2,4,6,8]
一次性调用整个列表执行某种操作,一次一列表式操作
返回fun的函数
Mult = fun(Times) -> (fun(X) -> X*Times end) end.
Triple = Mult(3).
Triple(5).
15
定义控制抽象
没有if,switch,for,while
想要额外的控制结构,可以自己创建。一切都是用匹配模型和高阶函数编写的。
for(Max,Max,F) -> [F(Max)]; for(I,Max, F) -> [F(I)|for(I+1),Max,F] lib_misc:for(1, 10, fun(I) -> I * I end). [1,4,9,16,25,36,49,64,81,100]
列表处理
sum -module (mylists). -export ([sum/1]). sum([H|T]) -> H + sum(T); sum([]) -> 0. L=[1,3,10]. [1,3,10] mylists:sum(L). map(_, []) -> []; map(F, [H|T]) -> [F(H)|map(F, T)].
列表推导
L=[1,2,3,4,5]. list:map(fun(X)->2*X end, L).
等价于
[2*X || X <- L].
[F(X) || X <- L].
F(X)组成的列表(X从列表L中提取)
total(L) ->
lists:sum([shop:cost(A)*B] || {A,B} <- L]).
简化map
map(F,L) -> [F(X) <- L].
列表推导表达式
生成器
Pattern <- ListExpr(列表表达式)
位串
BitStringPattern <= BitStringExpr
过滤器1、4的结构一致
[X || {a,X} <- [{a,1},{b,2},{c,3},{a,4},hello,"wow"]]. [1,4]
quickSort
-module (lib_misc).
-export ([qsort/1]).
qsort([])->[];
qsort([Pivot|T])->
qsort([X || X <- T, X < Pivot])
++ [Pivot] ++
qsort([X || X <- T, X >= Pivot]).
1> c(lib_misc).
{ok,lib_misc}
2> L=[23,6,2,8,27,400,78,56,73,85,11].
[23,6,2,8,27,400,78,56,73,85,11]
3> lib_misc:qsort(L).
[2,6,8,11,23,27,56,73,78,85,400]
比格拉斯三元数组
A*A=B*B + C*C
pythag(N) ->
[{A,B,C} ||
A <- lists:seq(1,N),
B <- lists:seq(1,N),
C <- lists:seq(1,N),
A+B+C =< N,
A*A + B*B =:= C*C
].
lists:seq(1,N)
返回一个包含1到N所有整数的列表
lib_misc:pythag(30).
[{3,4,5},{4,3,5},{5,12,13},{6,8,10},{8,6,10},{12,5,13}]
回文构词
perms([]) -> [[]];
perms(L) -> [[H|T] || H <- L, T <- perms(L -- [H])].
lib_misc:perms("cats").
["cats","cast","ctas","ctsa","csat","csta","acts","acst",
"atcs","atsc","asct","astc","tcas","tcsa","tacs","tasc",
"tsca","tsac","scat","scta","sact","satc","stca","stac"]
内置函数
list_to_tuple/1
关卡
通过使用关卡,可以对某个模式里的变量执行简单的测试和比较
max(X,Y) when X > Y -> X;
max(X,Y) -> Y.
通过when关键字引入
关卡序列,指单一或一系列关卡,用;
分隔,对于关卡序列G1;G2;G3...;Gn
,只要其中一个为true,值为true。关卡有一系列关卡表达式组成,用,
分隔。只有所在的所有关卡表达式都为true,才为true。
分号类似或的关系,逗号类型与的关系
合法的关卡表达式是所有合法erlang表达式的一个子集。确保无副作用。关卡是模式匹配的一种扩展。
合法的关卡表达式
1.原子true
2.其他常量(各种数据结构和已绑定常量),在关卡表达式中为false
3.调用后面表1里的关卡判断函数和表2里的内置函数
4.数据结构比较
5.算术表达式
6.布尔表达式
7.短路布尔表达式
关卡示例
fun(X,Y) when is_integer(X), X>Y, X<6 -> ...
X为整数,大于Y,小于6
true关卡的作用
if
Guard -> expressioons;
Guard -> expressioons;
Guard -> expressioons;
..
true -> expressioons
end.
case和if表达式
case expressions of
pattern1 [when Guard] -> Expr_sql1;
pattern2 [when Guard] -> Expr_sql2;
..
end.
if表达式
if
Guard1->
Expr_seq1;
Guard2->
Expr_seq2;
end.
(类似if elseif else)很多时候,if表达式的最后一个关卡是true,确保其他关卡都是失败时表达式最后部分会执行。
构建自然顺序的列表
some_funciton([H|T],..., result,...) ->
H1 = ... H ...,
some_function(T,...,[H1|result],...);
some_function([],...,result,...)->
{...,result,...}.
-
总是向列表头添加元素
-
从输入列表的头部提取元素,然后把他们添加到输出列表的头部,形成的是与输入类表相反的输出类别
归集器
odds_and_evens2(L) ->
odds_and_evens_acc(L,[],[]).
odds_and_evens_acc([H|T], Odds, Evens) ->
case (H rem 2) of
1 -> odds_and_evens_acc(T,[H|Odds],Evens);
0 -> odds_and_evens_acc(T,Odds,[H|Evens])
end;
odds_and_evens_acc([], Odds, Evens) ->
{Odds, Evens}.
lib_misc:odds_and_evens2([1,2,3,4,5,6]).
{[5,3,1],[6,4,2]}