第4章 模組與函式
阿新 • • 發佈:2018-12-16
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}.