Erlang学习笔记二

函数的重载

-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对数组进行分别处理,避免重复遍历。

 

你可能感兴趣的:(学习总结,erlang)