1.Erlang的互動式環境
安裝:下載並安裝Erlang,在OS的環境變數中添加pathErlangHOME\bin目錄
啟動:linux 環境:erl,windows: 開始-程式-erlang表徵圖啟動(或像linux輸入erl在CMD模式下啟動) 當然也可以在表徵圖模式下啟動,把原始碼放在另一個目錄中,要調用則要更改目錄,例如:1> cd("d:/program/Erlang").d:/program/Erlang ok .
退出:Ctrl+C 或者 halt().
現在也有Eclipse下的Erlang外掛程式,方便開發,不過目前還有很多bug。
Erlang shell:shell中會列印出1>,2>類似的行號
%表示注釋,例如:1>% I'm going to enter some expressions in the shell.. 注釋不會被Erlang編譯
在shell中直到你在運算式的末尾敲入一個結束符行號才不會一直顯示當前的行號,結束符是點號
在shell中當你打入一個括弧('(','{','[')符的結束符時,shell會提示你起始符的位置,然後再繼續輸入
當shell對你的指令沒反映的時候,你可以按入Ctrl+C中斷,系統會提示:BREAK:(a)bort (c)ontinue 等
你可以同時開啟多個shell視窗
2.不能變的變數
變數:所有的變數首字母應為大寫字母,小寫開頭不是變數。
1>X = 123456.
123456 ;
2>Xyz = 12345.
定義變數後,不能再給變數賦予另外的值,否則會出錯 1>X = 123. 2>X=234.
(出錯)原文:Erlang has single assignment variables.
3.變數類型
整型 : erlang支援任意大小的整型數進行運算,你不用擔心它會溢出、錯誤或者在一個字的大小內能否表示等問題。
例如:11> 123456789*987654321*112233445566778899*998877665544332211. = 13669560260321809985966198898925761696613427909935341
進位整數:還可以用2#,8#,16#,32#(最大)等進位進行算術,如: 1>2#11110000 * 2#00001111. = 3600 ,即10進位的240 * 15
1>8#7 * 8#6. = 42 ,即 10進位的7*6 = 42 ; 1>16#a * 16#b. = 110 16進位的a=10,b=11,結果即110。
浮點類型:除法 5/3 = 1.66667 4/2=2.00000 , "/"永遠返回浮點型; 商 5 div 3=1 , 4 div 2 = 2 ;餘數 5 rem 3 = 2 , 整數與浮點數進行運算,結果是浮點數
小技巧:f().方法會遺忘變數綁定的值,即可對一個變數多次賦值,此命令危險,是所有變數都遺忘。
atom類型(元子類型):原子類型是全域的,以小寫字母打頭,不同於變數的大寫。
元子只是一個簡單的名字,其它什麼都不是,他們不像變數一樣可以帶有值。如果您的程式中有一個參數是元子類型,如果你傳入不相同的元子則程式出錯
Tuples類型(元群組類型,python語言中有):類似C語言中的結構體。
Tuples具有垃圾自動回收功能,能自動釋放不用的記憶體,在Tuples中,符號"_(底線)"可以取任何變數值,不像有符號的變數,“_”不會出錯但也不綁定值。Tuples類型以“{”開頭,以”}“結尾。
Lists類型(清單類型):可以使用lists類型儲存任何數量的變數.lists變數以"["打頭,"]"結尾。Lists類型中可以有Tuples類型. 例如:[1+7,apples,{abc,10},123]
lists類型中如果有運算式的話,輸出的結果是運算式的值。如[1+7,20-20] 結果為[8,0]。
如果T是一個LIST類型,則[H|T]永遠是LIST類型, []代表一個空list,"|"表示分隔。
也可以從一個LIST中把值賦與一批元素變數類似:[Buy1|ThingsToBuy2] = ThingsToBuy1.也可以表“|”進行分隔,“|”前buy1對應一個元素,“|“後面的對應多個元素。
小結:可以把一批值放到LIST中,也可以把一批值給予一批變數,也可以用”|“進行有需求的分隔List。
Strings類型:嚴格的說在Erlang中沒有Strings類型,Strings類型僅僅是list與整型。Strings是用雙引號(“”)標識的
Strings類型也可以用LIST來表示,例如:[83,117,114,112,114,105,115,101].會表示出:"Surprise",但[1,2,3]還是會表示出[1,2,3],因為1-31都不是可列印字元,如果一個list有一個元素不是可列印字元則list不用string輸出
小技巧:在Erlang中,可以用“$"符(美元符)來表示一個字母的整型值,例$s = 115,上面的則可以用.來形象的表示 符號的作用:
符號運算:
=號:
在大多數語言中,=號是一個指派陳述式,但在Erlang中,不管怎麼樣=都是一個模式比對操作。例:X=(2+4). 與X=6.這兩句不會出錯,因為X=6是值進行匹配,
如果X=(2+4). X=3.這兩句一起執行就會出錯,因為6不等於3。 百分比符號(%) ,注釋符%% this is commet
逗號(, comma) ,分隔函數的參數,資料結構或者模式比對
點號(.period), 在shell中用以標識整個函數與運算式的結尾
分號(;semicolon) ,分割模組中的子句,一個函數中有多個相同的重載方法,則用分號分隔。 在case,if,try..catch,receive出現 。
豎線("|") 遍曆列表的方法,|運算後通常得到list的第一個元素。
如[First|TheRest] = [1,2,3,4,5],First=1,TheRest=[2,3,4,5].當然在|前加上值可以把list變的更長,可以由空變成一個list,例如把list反轉就可以應用此方法。
符號“||”(雙豎線)用來表示comprehensions操作。
=:= (值相等),判斷兩個值是否相等,類似JAVA中的==
<(小於) >(大於) =< (等於小於) ,>=(大於等於) , /=(不等於)
_(底線) ,匿名變數,這是一個簡化的,用於一個將得到值的變數,並且我們還需要丟棄這個值的情況下使用
modules(模組)
模組是Erlang代碼的基本單元。所有的函數將封裝在模組中,模組以尾碼為.erl的檔案形式進行儲存。模組在運行前必須被編譯,編譯模組為.beam檔案 一個簡單的模組geometry.erl
-module (geometry).
-export([area/1]).
area( {rectangle , Width ,Ht} ) ->Width * Ht ;
area( {circle,R } ) -> 3.14159 * R * R .
分析:
-module(filename) 指出模組的名字,注意filename要與檔案名稱一樣,類似JAVA
-export([area/1])指出模組有一個名為area的函數,並且帶有一個參數,模組中的方法area可以在其它模組被調用。也可以帶多個參數,比如-expot([area/1,mult/2]).
-import(lists,[map/2,sum/1]). 表示從外部參考模組的方法,這句就引用了模組lists中的兩個方法,map與sum
area有兩個字句,字句之間用分號(;)進行間隔, 結尾用(.)點號結束。兩個字句的參數均為tuple類型,tuple中有幾個參數則執行哪個子句 編譯modules模組:
1、建立一個.erl的檔案,啟動erl
2、輸入c(filename) 進行編譯,注意c是小寫,filename是函數名,函數名必須與erl的檔案名稱一樣,編譯後會產生一個檔案:filename.beam
3、執行erl檔案中的方法 filename:functionname(para) 分別是檔案名稱:函數名(參數)
4、如果有多個模組在多個不同的檔案中,把檔案編譯後在同一目錄下可以直接輸入filename名進行function引用。
個人小結:個人認為erlang環境做的最多的就是自動迭代與遞迴。例如[{M}|T],如果list參數有10個tuple,你只需用一條語句fn(M) + fn(T),則Erlang環境自動把參數拆解并迭代遞迴調用,直到程式完成。
內建函數(BIFs)
內建函數是一個因為某原因被內嵌在Erlang虛擬機器中的函數。BIFs經常是一些在Erlang上無法實現或者實現起來效率不高的東西,預設屬於Erlang摸塊下,比如trunc與erlang:trunc調用等同
可以用於條件判斷(守衛)的內建函數舉例:
trunc(5.6). : 5 (去小數點)
round(5.6). : 6 (四捨五入)
length([a,b,c,d]). : 4 (list求元素個數)
float(5). : 5.00000 (整形變成浮點型)
is_atom(hello). : true (判斷是否元子類型)
is_tuple({abc,{1,30}}). : true (判斷是否元群組類型)
以下的內建函數不能用於守衛,比如:
atom_to_list(hello). : "hello" (元子類型轉list)
list_to_atom("bye"). : bye (list類型轉元子)
integer_to_list(22). : "22" (整型轉list類型)
以上三個內建函數很難(不可能)在Eralng中實現
Funs(複雜函數) :
funs是一個匿名的函數,只所以這麼稱呼是因為這個函數沒有名字,但可以把函數指向一個變數,類似C中指向函數的指標。
例如:Z = fun(X) -> 2*X end. fun(X)是一個匿名函數,函數的主體是2*X ,把函數指向了變數Z,執行Z(2) = 4,即2*2 = 4.
fun(X)中的參數X可以為tuple,list,甚至還可以像C中的switch用多個參數,例如:fun(C,C) ->xxxxx ; (f,F) ->xxxxx ; (y,Y)->xxxx end.參數要對應匹配,傳遞的參數與申明的不一樣則拋出異常。
小技巧:lists 是Erlang的標準庫。有兩個有用的方法:lists:map(F,L)和lists:fliter(F,L),F:Funs,L:list對象。
map的功能是把L用F進行處理後返回一個新的List,Fliter的作用是把L按照F的方法進行過濾返回一個新List
例:L=[1,2,3,4] ,lists:map(Double,L) = [2,4,6,8]. Double = Fun(X) -> X * 2 end. 對於Fliter,如果經過運算得到的某一項的值為Flase則丟棄原List值。
Funs還可以進行嵌套,即一個函數返回一個fun對象,例如:Mu = fun(X) -> ( fun(Y) -> X * Y end) end. Tr = Mu(5) ;Tr(3) = 15.
我們還可以這樣使用fun ,例:lists:map(fun convert_to_c/1,List). 這句fun中是定義別處的一個函數,可以通過函數名/參數個數來使用
List Comprehensions (list 理解):
List comprehensions 即對list操作不使用funs,maps或者fliters等方法而實現對應功能的運算式。符號“||”(雙豎線)用來表示comprehensions操作。
以往的操作都是比如L=[1,2,3,4,5] ;lists:map(fun(X) -> X*2 end,L).實現[2,4,6,8,10],這些方式過於繁瑣,
可以使用[F(X) || X<-L] 來實現,F(X)的意思是List中的每一個項都給變數X,前面的例子因此可以簡寫成[2*X || X <- L] =[2,4,6,8,10],即把L中的每一個元素給X然後乘以2。這裡的X變數只是臨時的,語句過後X的值不存在,如果前面有語句已經定義X,則Erlang不會拋錯,X只適用於該語句。
再看這個例子:[X || {a,X} <- [{a,1},{b,2},{c,3},{a,4},hello,"WOW"] ].這個例子得到的值是[1,4],為什麼是list[1,4]呢?因為原子a在list中有兩個,因此得到1,4.
List Comprehensions的超強應用,超簡單排序演算法:
qsort([Pre|Nex]) -> qsort([X || X <- Nex , X <Pre]) // 一個list,經過[pre|Nex]運算後,得到pre的值,只取比pre小的值放前面,
++ [Pre] ++ // ++ 是list的串連操作符,語句產生的list前後加起來
qsort([X || X <- Nex , X>=Pre]). //一個list ,經過[pre|Nex]運算後,得到pre的值,只取比pre大的值放後面,然後erlang自動迭代遞迴,直到List中的最後一個值,排序完成,3行完成一個排序演算法
IF語句
樣本:
test_if(A,B) ->
Result = if
B == 6 -> io:format("B= 6~n",[]) , b_equals_6 ;
A == 5 -> io:format("A= 5~n",[]) , a_equals_5 ;
A == 2 , B == 3 -> io:format("A==2 , B==3 ~n",[]) , a_equals_2_b_equals_3;
A == 1 ; B == 7 -> io:format("A==1 ; B == 7 ~n",[]),a_equals_1_or_b_equals_7;
true -> nothging
end.
說明:
1.if 與 end. (注意點號匹配)
2.每條if語句後面帶分號(;),最後一條沒有,且每條if語句都有隱性的break功能,執行完後將退出if語句
3.第一條判斷將最先匹配
4.A==2 ,B ==3 中間的逗號表示 AND
5.A==1 ;B== 7 中間的分號表示 OR
6.if語句中直接寫元了類型將直接輸出元子
7.輸入的條件都不匹配的將拋出(if_clause)異常,除非最後有一句true
8.if與case語句都可有傳回值,上例中如果值為true,則Result的值為元子nothing.
CASE語句:
例:
case Length of
{centimeter ,X} -> {inch,X / 2.54};
{inch,Y} -> {centimeter,Y * 2.54 };
end.
說明:
1.case of end.匹配
2.可以用元群組類型(tuples)進行判斷
3.都帶有隱性的break功能。
4.if與case語句都可有傳回值