1. 程式人生 > >第4章 模組與函式

第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}.