第4章 模块与函数

1.模块

  • 1)在erlang中定义函数,在未编译前后缀名为.erl,编译后后缀名为.beam
  • 2)以geometry.erl模块为例,首先使用pwd(),显示出编译时所在的目录,如本机显示为D:/Erlang/erl7.3/usr ,故在该目录下,新建txt文件并修改后缀名为.erl,并输入内容:
    -module(geometry).
    -export([area/1]).
    
    area({rectangle,Width,Height}) ->Width*Height;
    area({square,Side}) ->Side*Side.

2.函数

  • 1)在编译器中运行 c(geometry). 然后就可以进行调用area()函数:
  • 1>geometry:area({rectangle,10,5}).
    50
    2>geometry:area({square,3}).
    9

3.模块代码内加测试

  • 1)给代码添加测试,在定义模块时,可以内置test代码,具体如下:
  • -module(geometry1).
    -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.

4.在一个模块中对另一个模块进行调用,并实现迭代list

  • 在一个模块中调用另一个模块的函数,配合list中的[头|尾]的方式,可以实现对list中的数据的迭代遍历.
  • 如:定义一个模块shop.erl
    -module(shop).
    -export([cost/1]).
    
    cost(oranges) ->5;
    cost(nespaper) ->8;
    cost(apples) ->2;
    cost(pears) ->9;
    cost(milk) ->7.
  • 然后再定义一个shop1.erl,内容如下:
  • -module(shop1).
    -export([total/1]).
    
    total([{What,N}|T]) ->shop:cost(What)*N + total(T);
    total([]) ->0.
  • 当输入 shop1:total([]). 时,输出结果为0;
    当输入shop1:total([{milk,3}]). 时,输出结果为21,注意,此时T=[],
    当输入shop1:total([{milk,3},{oranges,4}]). 时,输出结果为41,T1=[{oranges,4}],T2=[].

5.fun:基本的抽象单元,用于代表函数的数据类型

1>Double=fun(X) -> 2*X end.
#Fun<erl_eval.6.50752066>
2>Double(2).
4

3>Hypot=fun(X,Y) -> math:sqrt(X*X+Y*Y) end.
#Fun<erl_eval.12.50752066>
4>Hypot(3,4).
5.0

5> TempConvert=fun({c,C}) ->{f,32+C*9/5};
5> ({f,F}) ->{c,(F-32)*5/9}
5> end.
#Fun<erl_eval.6.50752066>
6> TempConvert({c,100}).
{f,212.0}
7> TempConvert({f,100}).
{c,37.7777777777778}

6.以fun作为参数的函数

Erlang的标准库中lists模块导出了一些以fun作为参数的函数,有list:map(F,L)和lists:filter(P,L),lists:member(X,L)

  • 1)lists:map(F,L):为列表L里的各个元素应用F生成.
    1>L=[1,2,3,4].
    2>lists:map(fun(X) -> 2*X end,L).
    [2,4,6,8]
  • 2)lists:filter(P,L):返回一个新的列表,内含L中所有符合条件的元素(条件时对元素E而言P(E)为true.
    应用:
    
    1>Even=fun(X) ->(X rem 2) =:=0 end. %% X rem 2表示求X除以2后的余数,=:=用来测试是否相等.
    2>Even(8). 
    true
    3>Even(7). 
    false
    4>lists:map(Even,[1,2,3,4,5,6,7,8]). 
    [false,true,false,true,false,true,false,true]
    5>lists:filter(Even,[1,2,3,4,5,6,7,8]). 
    [2,4,6,8].
  • 3)lsits:member(X,L):如果X是列表L中的成员,则返回true,否则返回false
    1>Fruit=[apple,pear,orange].
    2>MakeTest=fun(L) ->(fun(X) ->lists:member(X,L) end) end. 
    %%注意:MakeTest传入的第一个参数给了fun(L),然后进入fun(X)等待传值期
    3>IsFruit=MakeTest(Fruit). 
    %%将已经接收L参数后的MakeTest的指引给予IsFruit,所以IsFruit=fun(X) ->lists:member(X,L) end
    4>IsFruit(pear). 
    true
    5>lists:filter(IsFruit,[dong,orange,cat,apple,bear]). 
    [orange,apple]

7.自定义控制抽象

  • 1)实现for循环.
    -module(lib_misc).
    -export([for/3]).
    
    for(Max,Max,F) ->[F(Max)];
    for(I,Max,F) ->[F(I)|for(I+1,Max,F)]. %%利用头|尾的方法进行遍历
    
    ​
    1>c(lib_misc).
    2>lib_misc:for(1,10,fun(I) ->I end).
    [1,2,3,4,5,6,7,8,9,10]
    
    ​
    
  • 2)实现sum方法
    -module(mysum).
    -export([sum/1]).
    
    sum([H|T]) ->H+sum(T);
    sum([]) ->0.
    
    
    1>c(mysum).
    2>mysum:sum([1,2,3,4,5].
    15
  • 3)实现map方法
    -module(mymap).
    -export([map/2]).
    
    map(_,[]) ->[];
    map(F,[H|T]) ->[F(H)|map(F,T)].
    
    
    1>c(mymap)
    2>mymap:map(fun(X) ->X*X end,[1,2,3,4,5]). 
    [1,4,9,16,25]

8.列表推导

      列表推导常规的形式:[X || Qualifier1,Qualifier2,....]X是任意一条表达式,后面的限定符(Qualifier)可以是生成器,位串生成器或过滤器.生成器的写法是:Pattern <-ListExpr ,其中的ListExp必须是一个能够得出列表的表达式位串生成器的写法是:BitStringPattern <= BitStringExpr ,其中的BitStringExpr必须是一个能够得出位串的表达式过滤器既可以是判断函数(即返回true或false的函数),也可以是布尔表达式.

1>[2*X || X<-[1,2,3,4]]. 
[2,4,6,8]
2>[X|| {a,X} <-[{a,1},{b,2},{c,3},{a,4},hello,"wow"]].
[1,4] 
%%应用的是过滤器
%%实现快速排序算法
-module(quicksort).
-export([sort/1]).

sort([]) ->[];
sort([H|T]) ->
sort([X || X<-T , X<H]) ++ [H] ++ sort([X || X<-T,X>=H]).
%%注意++的作用是字符连接
%%该算法将T分为两部分,一部分小于H,一部分大于H,然后再循环调用.


1>quicksort:sort([3,61,1,8,22,754,35,36,36,90,34]). 
[1,3,8,22,34,35,36,36,61,90,754]
%%毕达哥拉斯三元数组
-module(lasi).
-export([pythag/1]).

pythag(N) ->
[{A,B,C} ||
A <-lists:seq(1,N), %lists:seq实现对1到N的遍历
B <-lists:seq(1,N),
C <-lists:seq(1,N),
A+B+C=<N, %注意=<符号
A*A+B*B =:=C*C %注意=:= 符号
].
%%回文构词
-module(perms).
-export([perms/1]).

perms([]) -> [[]];
perms(L) -> [[H|T] || H<- L,T<- perms(L--[H])]. %--的作用是从L中删除H

9.内置函数

  • list_to_tuple:将一个列表转变成元组
  • time() :得出现在的时分秒

10.关卡

  • 1)when
    • f(X,Y) when is_integer(X), X>Y ,Y<6 -> ..... 表示当X是一个整数,X大于Y且Y小于6时
  • 2)and andalso or orelse xor not
    • and  如果两个参数都是真,那么就返回真
    • andalso and的快捷计算,第一参数为假,则返回假,不需要计算第二个参数
    • or 如果两个参数任一个为真,则返回真
    • orelse or的快捷计算,第一参数为真,就返回真,不需计算第二个参数
    • xor 异或
    • not 否定运算
  • 3)true关卡
    • if Guard -> Ex; Guard1 ->Ex1; ........ true -> Ex ; 相当于finally
  • 4)case
    • case Expression of
    • Pattern1 -> Ex1;
    • Pattern2 -> Ex2;
    • .....
    • end.
  • 5)if
    • if
    • Guard1 -> Ex1;
    • Guard2 -> Ex2;
    • ......
    • end

11.构建自然顺序的列表:最有效率的方法是向某个现成列表的头部插入元素

12.归集器的实现

%%以分奇数偶数为例
odds_and_evens2(L) ->
odds_and_evens_acc(L,[],[]).
odds_and_evens_acc([H|T],Odds,Evens) ->
case (H rem 2) of
1 -> odds_and_evens_acc(T,[H|Odds],Evens);
0 -> odds_and_evens_acc(T,Odds,[H|Evens])
end;
odds_and_evens_acc([] ,Odds,Evens) ->
{Odds,Evens}.

猜你喜欢

转载自blog.csdn.net/qq_34755443/article/details/84314435
今日推荐