erlang-基本语法_5、记录(record)、guard、高

2018-06-15  本文已影响0人  zhang_yongfeng

写在前面

本文主要是以一个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

上一篇下一篇

猜你喜欢

热点阅读