erlang-基本语法_5、记录(record)、guard、高
写在前面
本文主要是以一个erlang的学习记录,有错误的地方欢迎指正。
Snip20180615_24.png记录 record
记录其实就是元组的另一种形式。通过使用记录,可以给元组里的各个元素关联一个名称。
何时使用记录
当你可以用一些预先确定且数量固定的原子来表示数据时;
当记录里的元素数量和元素名称不会随时间而改变时;
当存储空间是个问题时,典型的案例是你有一大堆元组,并且每个元组都有相同的结构
新建一个文件 record.erl,代码如下:
-module(record).
% 定义一个记录
-record(book,{author, bookname, chapters = 0}).
% 编译文件
1> c(record).
{ok,record}
2>
%在Erlang的shell中,如果想创建record的实例,必须先读取记录的定义,使用命令rr(read record)
3> rr("record.erl").
[book]
% 创建记录
4> Shuihu = #book{author ="edit", bookname= "haliboke"}.
#book{author = "edit",bookname = "haliboke",chapters = 0}
% 更新记录
6> Shuihu2 = Shuihu#book{chapters = 36}.
#book{author = "edit",bookname = "haliboke",chapters = 36}
% 提取记录.
7> #book{author = Author1 , bookname= Bookname,chapters = Pirse} = Shuihu.
#book{author = "edit",bookname = "haliboke",chapters = 0}
8> Author1.
"edit"
9> Bookname.
"haliboke"
10> pirse.
pirse
11> Pirse.
0
12>
Erlang匹配、Guards与变量的作用域
示例:在列表中找出最大的值,新建一个tut6.erl文件如下:
-module(tut6).
-export([list_max/1]).
list_max([Head|Rest]) ->
list_max(Rest,Head).
list_max([], Res) ->
Res;
%when 用在函数的 -> 前时是一个特别的的单词,
%它表示只有测试条件为真时才会用到函数的这一部分。
%这种类型的测试被称这为 guard 如果 guard 为假 (即 guard 测试失败),
%则跳过此部分而尝试使用函数的后面一部
list_max([Head|Rest],Result_so_far) when Head > Result_so_far ->
list_max(Rest,Head);
%每个变量在其作用域内只能被赋值一次。
%从上面的例子中也可以看到,Result_so_far 却被赋值多次。
%这是因为,每次调用一次 list_max/2 函数都会创建一个新的作用域。
%在每个不同的作用域中,Result_so_far 都被当作完全不同的变量。
list_max([_Head|Rest],Result_so_far) ->
list_max(Rest,Result_so_far).
%编译
3> c(tut6).
{ok,tut6}
%调用方法,找出列表中最大的值
4> tut6:list_max([1,2,3,4,5,33,4,5,6,7,8]).
33
5>
guard
when 用在函数的 -> 前时是一个特别的的单词,
它表示只有测试条件为真时才会用到函数的这一部分。
这种类型的测试被称这为 guard
guard 中的操作符还包括:
<小于
> 大于
== 等于
>= 大于或等于
=< 小于或等于
/= 不等于
作用域
每个变量在其作用域内只能被赋值一次。
从上面的例子中也可以看到,Result_so_far 却被赋值多次。
这是因为,每次调用一次 list_max/2 函数都会创建一个新的作用域。
在每个不同的作用域中,Result_so_far 都被当作完全不同的变量。
匹配操作符
5> {X,Y} = {paris,{f,28}}.
{paris,{f,28}}
6> X.
paris
7> Y.
{f,28}
8>
高阶函数 (Fun)
在shell中定义了一个数值翻倍的函数
1> Xf = fun (X) -> X * 2 end.
#Fun<erl_eval.6.52032458>
2> Xf(5).
10
3>
操作列表处理函数 foreach 、 map
foreach(Fun,[First|Rest]).
Fun(First),
foreach(Fun,Rest);
foreach(Fun,[])->
ok.
map(Fun, [First|Rest]) ->
[Fun(First)|map(Fun,Rest)];
map(Fun,[])->
[].
在 shell 中使用 map 的 Xf 函数生成一个新的列表:
1> Xf = fun (X) -> X * 2 end.
#Fun<erl_eval.6.52032458>
2> Xf(5).
10
3>
3>
3> lists:map(Xf,[1,2,3,4]).
[2,4,6,8]
4>
输出一组城市的温度值
4> Print_City = fun({City,{X,Temp}}) -> io:format("~-15w ~w ~w~n",[City, X, Temp]) end.
#Fun<erl_eval.6.52032458>
6> lists:foreach(Print_City,[{moscow,{c, -10}},{cape_town, {f, 70}},{stockholm, {c, -4}},{paris,{f, 28}},{londom,{f,36}}]).
moscow c -10
cape_town f 70
stockholm c -4
paris f 28
londom f 36
ok
7>
遍历城市温度列表并将每个温度值都转换为摄氏温度表示
-module(tut13).
-export([convert_list_to_c/1]).
convert_to_c({Name,{f, Temp}}) ->
{Name, {c, trunc((Temp - 32 ) * 5 / 9)}};
convert_to_c({Name, {c, Temp}}) ->
{Name, {c, Temp}}.
convert_list_to_c(List) ->
lists:map(fun convert_to_c/1,List).
%编译
8> c(tut13).
{ok,tut13}
9>
9> tut13:convert_list_to_c([{moscow,{c,-10}}]).
[{moscow,{c,-10}}]
11>
11> tut13:convert_list_to_c([{moscow, {c, -10}}, {cape_town, {f, 70}},
11> {stockholm, {c, -4}}, {paris, {f, 28}}, {london, {f, 36}}]).
[{moscow,{c,-10}},
{cape_town,{c,21}},
{stockholm,{c,-4}},
{paris,{c,-2}},
{london,{c,2}}]
匿名变量
fun({_,{c,Temp1}},{_,{c, Temp2}})-> Temp1 < Temp2 end.
这儿用到了匿名变量 "_" 的概念。匿名变量常用于忽略一个获得的变量值的场景下。
当然,它也可以用到其它的场景中,而不仅仅是在高阶函数这儿。
Temp1 < Temp2 说明如果 Temp1 比 Temp2 小,则返回 true。
引用网络博客内容:
https://www.w3cschool.cn/erlang/tohb1p5z.html (w3cschool erlang教程)
个人博客地址:https://zhangyongfeng1.github.io/
简书地址:https://www.jianshu.com/u/137f325832fb