Erlang學習記錄(二)——基本數據類型


Erlang可以說和我以前接觸過的語言都大不相同,這個從它的類型定義就可以看出來。。。反正學起來覺得既不熟悉,也不親切,我估計在用Erlang寫應用的時候,整個編程思路都要變一下了。不過存在即是合理的,鑒於Erlang在面向並發,輕量進程,方便的數據處理還有容錯性上的巨大優勢,還是咬咬牙學吧!

 

在講述數據類型前先簡單的介紹一下Erlang中的變量,Erlang中的變量和其他語言中的變量相比有三點不同:

1.Erlang不對變量的類型進行定義,它可以被賦值成任何類型的值,Erlang中所有類型的值統稱為一個Term。這使得編譯器並不能在編譯時發現數值類型的不匹配,只有在運行時發現錯誤,好處是不像C++一樣能通過強制類型轉換蒙蔽系統,造成內存泄露,也使得Erlang不像C++一樣易於發現代碼中的問題。不過Erlang現在已經有一套類型,函數的定義機制,能通過dialyzer來查找代碼中的不匹配了。

2.Erlang中的變量只能被賦值一次,第二次賦值將被編譯器理解為進行比較,如果值相同將返回該值,如果不同將會拋出異常。

3.Erlang中的變量必須以大寫字母或下划線打頭,否則將不被編譯器理解為變量,且大寫字母打頭和下划線打頭的變量有些不同的行為。

 

一.Number

1.支持數字和浮點型。

2.浮點可表示為2.3,2.3e3,2.3e-3等類型。

3.支持用$char來獲取字符的ASCII值

4.支持進行2-36進制數的表示,如3#11表示4.

 

二.Atom

有點類似於常值。它一般都是由小寫字母打頭的字母組成的,如果其以大寫字母打頭,或者含有除字母,下划線,@之外的字符,則需要用單引號引起來表示Atom。

Atom比C++中的常量更方便易用,比如我們可以直接用circle,line來代表不同的圖形類型。而不用先定義CIRCLE,LINE常量。

Atom好用但是不能濫用,因為用Atom有下面幾點弊端:

1.Atom保存在atom table中,一個Atom占用4個(32bit)或8個(64bit)字節,且會持續的占用內存,不參與垃圾回收,另外其本身也有不能超過1048577個的限制。

2.Atom只能進行比較,而不能進行任何的處理操作,比如分隔,匹配等等。

 

Erlang中的保留字有:

after and andalso band begin bnot bor bsl bsr bxor case catch cond div end fun if let not of or orelse query receive rem try when xor

 

三.Tuple

類似於Object,不同的是,它的長度是固定的,形式如下:

{Term1,...,TermN}

可以用模式匹配的方式輕松的獲取Tuple中的某一值。

 

四.List

形式如下:

[Term1,...,TermN]

可以用|來連接Head和Tail,其中Head可以是任意Term,而Tail必須是List。

如[1|2]雖然能正常執行,但是卻不能被length等內置函數使用。

需要注意的是:

length(1|[2,3])為3,但是

length([1,2]|3)為2

可以用模式匹配的方式依次獲取List的Head。

 

List還支持查詢式的操作,用法如下:

NewList = [Expression || GeneratorExp1, GeneratorExp2, ..., GeneratorExpN, Condition1, Condition2, ... ConditionM]

如,X取值為1或5,Y取值為6或7,我們要找到和能被3整除的X和Y.

[{X,Y}||X<-[1,5],Y<-[6,7],(X+Y) rem 3 =:=0].

 

輸出[{5,7}]

 

五.Bit Strings

Bit Strings代表無類型的內存區域,表現形式為<<E1,...,En>>。

其中Ei的形式為Value 或 Value:Size 或 Value/TypeSpecifierList 或 Value:Size/TypeSpecifierList

TypeSpecifierList的形式為Type-Signedness-Endianness-unit:IntegerLiteral.

其中Type可以是integer(default),float,binary,bytes,bitstring,bits,utf8,utf16,utf32形式的

Signedness可以是signed或者unsigned(default)

Endianness可以是big(default),little,native

IntegerLiteral取值范圍是1-256,這個數值用來擴展內存區域,將原來的區域擴展Size*(IntegerLiteral-1)位,默認值為1,即不進行擴展。

可以用模式匹配的方式輕松的獲取內存區域中某一位置的值,用Erlang來處理數據很方便,但是不推薦使用Erlang來處理大量的數據,因為Erlang在數據處理方面比C++慢。

 

當Bit Strings中所有的Ei的Size都為8時,叫做Binaries。

Binaries也支持查詢式的操作,實際上Binaries能查詢得到List,List也能查詢得到Binary。最直觀的還是舉例來看一下。

1.List得到List

[2*N || N <- [1,2,3,4]].
[2,4,6,8]

 

2.List得到Binary,注意要寫明類型或size。

<<<<(N*2):8>> || N <- [1,2,3,4]>>.
<<2,4,6,8>>

 

3.Binary得到List,注意<-變成了<=

[2*N || <<N>> <= <<1,2,3,4>>].
[2,4,6,8]

 

4.Binary得到Binary

<<<<(N*2):8>> || <<N>> <= <<1,2,3,4>>>>.
<<2,4,6,8>>

 

 

六.Fun

函數對象,有兩種方法給函數對象賦值

1.將一個匿名函數賦值給函數對象。

匿名函數的形式如下:

fun
    (Pattern11,...,Pattern1N) [when GuardSeq1] ->
        Body1;
    ...;
    (PatternK1,...,PatternKN) [when GuardSeqK] ->
        BodyK
end

 

2.將一個已經定義的函數賦值給函數對象。形式如下:

fun Name/Arity
fun Module:Name/Arity

其中Name表示函數名,Arity表示參數的個數。

 

七.String

String由雙引號和字符串來表示,其實質是List。如"hello"等價於[$h,$e,$l,$l,$o].

兩個相鄰的字符串將組合成一個字符串,即"he" "llo"等價於"hello"。

也可以用Binary來表示字符串。

 

八.Record

Record類似於Struct,Record表達式會在編譯時轉為tuple表達式。

1.定義Record:

-record(Name, {Field1 [= Value1],
               ...
               FieldN [= ValueN]}).

 

2.新建Record:

#Name{Field1=Expr1,...,FieldK=ExprK}

其中某些Field可以省略,這時這些Field將獲得默認值。

 

如果需要將多個Field賦同一值,可以用下面的方式:

#Name{Field1=Expr1,...,FieldK=ExprK, _=ExprL}

這時所有省略的Field都將被賦值成ExprL

 

3.訪問Field:Expr#Name.Field

 

4.更新Field

Expr#Name{Field1=Expr1,...,FieldK=ExprK}

 

九.Boolean

沒有該類型,但是可以用true和false代表Boolean值。true和false可以正常的用在一些進行判斷的場合,如:

true and false.
false or true.
true xor false.
not false.
not (true and true).

但是不能和C++中一樣,當成數字來用,要牢記,在Erlang中,它是Atom值。

 

十.類型轉換

1.除了tuple_to_list轉換成list時都會盡力轉成字符串形式

atom_to_list(hello).
"hello"
binary_to_list(<<"hello">>).
"hello"
binary_to_list(<<104,101,108,108,111>>).
"hello"
float_to_list(7.0).
"7.00000000000000000000e+00"
integer_to_list(77).
"77"

tuple_to_list({a,b,c}).
[a,b,c]


2.Number轉binary都轉成了字符串

integer_to_binary(77).
<<"77">>
float_to_binary(7.0).
<<"7.00000000000000000000e+00">>

 

3.其他的轉換

list_to_atom("hello").
hello
list_to_binary("hello").
<<104,101,108,108,111>>
list_to_float("7.000e+00").
7.0
list_to_integer("77").
77
list_to_tuple([a,b,c]).
{a,b,c}
term_to_binary({a,b,c}).
<<131,104,3,100,0,1,97,100,0,1,98,100,0,1,99>>
binary_to_term(<<131,104,3,100,0,1,97,100,0,1,98,100,0,1,99>>).
{a,b,c}
binary_to_integer(<<"77">>).
77
binary_to_float(<<"7.000e+00>>").
7.0

 

十一.類型判斷

is_atom/1           
is_binary/1        
is_bitstring/1      
is_boolean/1        
is_builtin/3       
is_float/1          
is_function/1       is_function/2      
is_integer/1        
is_list/1           
is_number/1        
is_pid/1            
is_port/1           
is_record/2         is_record/3         
is_reference/1      
is_tuple/1

 

十二. 后記

除了上述類型之外,還有一些特別的類型,如reference(),pid(),port()等將在以后介紹。

 

參見:http://www.erlang.org/doc/reference_manual/data_types.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM