模块是存放代码的地方
模块保存在扩展名为.erl的文件里,编译后生成.beam
geometry.erl
-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.
//调用,下面这个是shell 里的命令
c(geometry).
geometry:area({rectangle,10,5}).
geometry:area({square,3}).
模式匹配循环使用
shop.erl
-module(shop).
-export([cost/1]).
cost(oranges) -> 5;
cost(newspaper) -> 8;
cost(apples) -> 2;
cost(milk) -> 7.
shop1.erl 调用total 计算Buy = [{oranges,4},{newspaper,2},{milk,7}] 的价格,这里的数字代表数量
-module(shop1).
-export([total/1]).
total([{What,N}|T]) -> shop:cost(What) * N + total(T);
total([]) -> 0.
fun
代表函数的数据类型被称为fun。(lambda)
Double = fun(x) -> 2 * x end.
Double(2). //结果=4
求三角形斜边
Hypot = fun(X,Y) -> math:sqrt(X*X + Y*Y) end.
Hypot(3,4). //结果是5.0
fun里的模式匹配,个转换华氏与摄氏温度
TempConvert = fun({c,C}) -> {f,32 + C * 9/5};
({f,F}) -> {c,(F-32)*5/9}
end.
lists:map 传递一个list过来然后消耗里面的值(消耗L里的值)
L = [1,2,3,4].
lists:map(fun(x) -> 2*X end,L).
=:= 判断是否相等
Even = fun(X) -> (X rem 2) =:= 0.
//结果 [false,true,false,true,false,true....]
lists:map(Even,[1,2,3,4,5,6,7]).
//结果 [2,4,6,8]
lists:filter(Even,[1,2,3,4,5,6,7,8]).
查询是否包含子元素,进2层,出2层
Fruit = [apple,pear,orange].
MakeTest = fun(L) -> (fun(X) -> lists:member(X,L) end) end.
IsFruit = MakeTest(Fruit).
//true
IsFruit(pear).
//false
IsFruit(dog).
//[orange,apple]
lists:filter(IsFruit,[dog,orange,cat,apple,bear]).
生成按照一定规律的递增数
for(Max,Max,F) -> [F(Max)];
for(I,Max,F) -> [F(I)|for(I+1,Max,F)].
//shell调用
//[1,2,3,4,5,6,7,8,9]
lib:for(1,10,fun(I) -> I end).
//[1,3,9,16,25]
lib:for(1,5,fun(I) -> I*I end).
导入其他元组里的方法(元组内求和) 。(import 导入的方法可以直接使用,否则需要使用完全限定shop:cost)
-module(shop2).
-export([total/1]).
-import(lists,[map/2,sum/1]).
total(L) ->
sum(map(fun({What,N}) -> shop:cost(What) end,L)).
列表推导
L = [1,2,3,4,5].
//新列表由原列表元素 * 2组成
[2*X || X <- L].
//计算总价
Buy = [{oranges,4},{apples,6},{milk,3}].
//名称转成价格
[{shop:cost(X),Number} || {X,Number} <- Buy].
//价格与数量相乘
[shop:cost(X) * Number || {X,Number} <- Buy].
//求和
lists:sum([shop:cost(X) * Number || {X,Number} <- Buy]).
//简化
map(F,L) -> [F(X) || X <- L].
//有过滤的作用,结果是[1,4]
[ X || {a,X} <- [{a,1},{b,2},{c,3},{a,4},"Hello","world"]].
排序算法(感觉类似快速排序),每次找到一个元素,小于它的元组放左边,大于的放右边。然后在分好的元组内继续找。
++ [Pivot] ++ //把元素与左右元组连接
qsort([]) -> [];
qsort([Pivot|T]) ->
qsort([X || X <- T,X < Pivot])
++ [Pivot] ++
qsort([X || X <- T, X >= pivot]).
毕达哥拉斯三元数组(名字像哥斯拉),勾股定理的三条边
lists:seq(1,N) 随机生成1~n的数,满足毕达哥拉斯三元组定理(感觉就是穷举,影响效率吧?)
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
].
回文构词(排列组合)(这个挺牛逼的,比java方便多了)
L -- [H] 从L种移除H元素。元组内遍历取第一个位置,剩下的依次取第二第三。。。。
perms([]) -> [[]];
perms(L) -> [[H|T] || H <- L,T <- perms[l--[H]]].
关卡(一种结构,增加模式匹配的威力)
获取最大值,when类似if的作用,逗号是并且,分号是或者
max(X,Y) when X > Y -> X;
max(X,Y) -> Y.
//,逗号是并且的意思
//T是一个包含六个元素的元组,T中第三个元素的绝对值大于5,元组X的第4个元素与列表L的列表头相同
is_tuple(T), tuple_size(T) =:= 6,abs(element(3,T)) > 5
element(4,X) =:= hd(L)
//;分号是或者,is_integer是整数判断
X =:= dog; X =:= cat
is_integer(X),X > Y; abs(Y) < 23
也可以直接使用 or、orelse、and、andalse。(or、and 类似java里的| 、& 而orelse,andalse类似 || 、&&会断路 )
true (放在最后)关卡相当于else ,当其他失败时进入这个匹配
//失败
f(X) when (X == 0) or (1/X >2) -> ...
//成功
f(X) when (X == 0) orelse (1/X >2) -> ...
if
Guard -> Expressions;
Guard -> Expressions;
true -> Expressions
end
case 和 if
filter(P,[H|T]) ->
case P(H) of
true -> [H|filter(P,T)];
false -> filter(P,T)
end;
filter(P,[]) -> [].
//不使用case
filter(P,[H|T]) -> filterl(P(H),H,P,T);
filter(P,[]) -> [].
filterl(true,H,P,T) -> [H|filter(P,T)];
filterl(false,H,P,T) -> [filter(P,T)].
erlang 如果没有true 关卡,最后少判断会报错
if
A > 0 -> do_this();
true -> do_ther()
end
自然顺序的列表:
- 从输入列表的头部提取元素,然后把它们添加到输出列表的头部,形成的结果是与输入,列表顺序相反的输出列表。
- 如果顺序很重要,就调用lists:reverse/1这个高度优化过的函数。
list ++ [H] 在数据量很少的时候使用,否则会影响效率。
一次遍历,元素分组
odds_and_evens2(L) ->
odds_and_evens_acc(L,[],[]).
odds_and_evens_acc([H|T],Odds,Events) ->
case(H rem 2) of
1 -> odds_and_evens_acc(T,[H|Odds],Evens);
2 -> odds_and_evens_acc(T,Odds,[H|Evens])
end;
odds_and_evens_acc([],Odds,Evens) ->
{Odds,Evens}.