函数的重载
-module(geometry).
-export([area/1]).
area({rectangle,Width,Height}) -> Width * Height;
area({square,Side}) -> Side * Side.
通过传输元组的方式,可以实现方法的重载,会根据模式匹配自己寻找合适的匹配方法体。被export声明的方法就是公有方法,而未被声明的就变成私有方法。
shell的操作
pwd() 查看当前路径·
ls() 查看当前路径下的文件
cd(Dir) 跳转路径到Dir路径下
测试模块
-module(geometry1).
-export([test/0,area/1]).
test() ->
12 = area({rectangle,3,4}),
25 = area({square,5}),
ok.
area({rectangle,Width,Height}) -> Width * Height;
area({square,Side}) -> Side * Side.
通过使用断言式的测试模块,可以确定函数是否会符和自己心意的运行。
何时使用何种标点符号
当并列列举时候分号,当表示顺序执行逗号,当完成一个语句时候句号
尾递归优化
sum(1) -> 1;
sum(N) -> N + sum(N - 1).
理论上说放在最后递归会被优化,但是假如最后一句不止调用方法,会被优化吗?
很遗憾并不会,可以注意到在进行递归时候,N的值将会被保存,用于当后面计算完之后相加,当列数值趋于无限大时候,需要保存的值也是无穷大的。这时候需要对进行优化:
tail_sum(N) -> tail_sum(N, 1).
tail_sum(1, Result) -> Result;
tail_sum(N, Result) -> tail_sum(N - 1, N + Result).
快乐枚举
-module(shop).
-export([cost/1]).
cost(oranges) -> 5;
cost(newspaper) -> 8;
cost(apples) -> 2;
cost(pears) -> 9;
cost(milk) -> 7.
在这个例子中,通过shop:cost(TypeName)的方式去访问枚举,然后会返回每个枚举对应的值。
而基于这个枚举,可以试试之前的列表清单:
total([{What,N}|T]) ->
shop:cost(What) * N + total(T);
total([]) -> 0.
通过这样,我们就可以计算一个购物清单总共多少钱。
fun函数
test() ->
Temp = fun({c,C}) -> {f,32+C*9/5};
({f,F}) -> {c,(F-32)*5/9}
end,
Temp({c,55}).
通过赋值给常量,可以把函数当作变量来互相传递使用
列表函数
Temp = fun(X) -> (X rem 2) =:= 0
end,
lists:map(Temp,[5,4,66,43]).//[false,true,true,false]
lists:filter(Temp,[5,4,66,43]).//[4,66]
通过使用map和filter可以使用自定义函数对列表进行操作
生成函数的函数
Temp = fun(X) -> (fun(Key) -> lists:member(Key,X) end)
end,
Go = Temp([3,5,6,7]),
Go(9).//false
通过Temp生成器,生产了一个Go的筛选器,输入9之后就可以判断出结果
自定义控制语句
for(Max,Max,F) -> [F(Max)];
for(I,Max,F) -> [F(I)|for(I+1,Max,F)].
test() ->
for(1,10,fun(X) -> X*X end).//[1,4,9,16,25,36,49,64,81,100]
列表推导
Key = [{tang,20},{ye,24},{li,44},{tu,65},{org,57}],
[{Name,Number*20}||{Name,Number}<-Key].//列表推导
//[{tang,400},{ye,480},{li,880},{tu,1300},{org,1140}]
使用列表推导可以简化进行列表的处理操作
快速排序的实现
easySort([]) ->
[];
easySort([Key|T]) ->
easySort([X||X<-T,X=Key]).
使用列表推导可以写出简洁的排序实现
回文数字检索
getSu()->
Scope = lists:seq(0,9),
[A*10000+B*1000+C*100+D*10+E||
A <- Scope,B <- Scope,
C <- Scope,D <- Scope,
E <- Scope,A=:=E,B=:=D,
A/=0].
很有趣的是,你可以使用列表推导来实现一些很复杂的逻辑判断,而看起来就像你在写sql语句似的。
++操作符和--操作符
使用++操作符进行数组拼接,使用--操作符来取出数据
实现全部顺序可能
perms([])->
[[]];
perms(T)->
[[Head|Tail]||Head <- T,Tail <- perms(T--[Head])].
>perms("123").//["123","132","213","231","312","321"]
该算法实现的是随机排列,可以将输入的内容所有组合方式列举出来
内置函数
list_to_tuple([xx,yy,zz]) //{xx,yy,zz}
time() //获得当前时间
关卡的使用
test() ->
toWhen(5).
toWhen(X) when X > 0,X /= 1 -> X;
toWhen(X) -> -X.
toWhen将输入的数值变为正数,并且假如遇到1会输出-1.这里列举出了关卡如何写以及多判断情况,逗号是and分号是or
关卡中的分号 or orelse
需要注意分号等同于orelse,其是短路式的,当前面正确就会跳过后者。or则会计算左右两边的值再进行或者。同理的还有逗号与andalso
true关卡的使用
作为一个来着不拒的关卡,可以负责接受其他关卡不要的东西。
关卡判断函数
is_atom(X) 是原子
is_binary(X) 是二进制型
is_constant(X) 是常量
is_float(X) 是浮点
is_function(X) 是fun
is_function(X,N) 是带有N个参数的fun
is_integer(X) 是整数
is_list(X) 是列表
is_map(X) 是映射组
is_number(X) 是整数或浮点数
is_pid(X) 是进程标识符
is_pmod(X) 是参数化模块的实例
is_port(X) 是端口
is_reference(X) 是引用
is_tuple(X) 是元组
is_record(X,Tag) 是类型为Tag的记录
is_record(X,Tag,N) 是类型为Tag大小为N的记录
abs(X) 绝对值
byte_size(X) X的字节数,X为位串或者二进制
element(N,X) X中第N个元素的值
float(X) 将X转换为浮点值
hd(X) 列表X的列表头
tl(X) 列表X的尾部
length(X) 列表X的长度
node() 当前的节点
node(X) 创建X的节点,X为进程、标识符、引用或端口
round(X) 将X转换为整数
self() 当前进程的标识符
size(X) X的大小,X为元组或二进制型
trunc(X) 将X去掉小数取整
tuple_size(X) 元组X的大小
case的应用
Key = {tang,1},
case Key of
{tang,Age} when Age<0 -> "error age";
{tang,Age} when Age<16 -> "no";
{li,Age} when Age>0 -> "no tang";
{tang,Age} when Age>16 -> "yes"
end.
可以看到这是一个case,前面的参数是匹配,而如果有需要可以在匹配的基础上对里面值进行关卡判断。
if的应用
if
A>0 -> ...
A<0 -> ...
true -> ...
end.
无论如何都应该有一个true,否则会报错,此外case也要注意如果没匹配中也会报错
反转列表
使用lists:reverse来对列表进行翻转操作,避免使用++和--符号来进行拼接,因为这会非常低效率
归集器
当希望返回两个或以上结果的时候,可以用列表来存储,在取出来的时候进行模式匹配即可。此外假如是对同个数组多次操作的,可以善用case和if对数组进行分别处理,避免重复遍历。