本系列文章是《Programming Erlang》的學(xué)習(xí)筆記
Erlang是什么
Erlang是由Ericsson開發(fā)的一種面向并發(fā)環(huán)境的函數(shù)式編程語言,
Erlang的并發(fā)性是語言虛擬機(jī)支持的思劳,不依賴于OS侨嘀。
Getting Stared
Erlang是面向并發(fā)環(huán)境的編程語言,一個Erlang程序是由多個并行的進(jìn)程構(gòu)成的八匠。進(jìn)程執(zhí)行模塊中定義的函數(shù)絮爷。一個erl文件包含一個模塊,編譯后的erl文件就可以在shell中直接執(zhí)行了臀叙。
-module(hello).
-export([start/0]).
% Hello erlang
start() ->
io:format("Hello Erlang!~n").
進(jìn)入Erlang Shell(erl)略水,就可以運(yùn)行這個模塊了
使用c(hello).編譯hello模塊使用hello:start().調(diào)用start函數(shù),即可看見運(yùn)行結(jié)果
$ erl
1> c(hello).
{ok, hello}
2> hello:start().
Hello Erlang~
ok
3> halt().
$
這是一個最簡單的Erlang模塊劝萤,我們可以通過這個模塊學(xué)習(xí)一下Erlang的基本語法渊涝。
- 不難發(fā)現(xiàn),所以Erlang語句都以.結(jié)尾床嫌,一個Erlang語句以.+空白結(jié)束跨释,空白可以是換行符,空格厌处,tab鳖谈,等等
- -module(hello).聲明了一個名為hello的模塊
- -export([start/0]).是這個模塊的導(dǎo)出函數(shù)列表,聲明了可以在模塊外部調(diào)用的函數(shù)列表阔涉,start/0表示start函數(shù)有0個參數(shù)
- start() -> io:format("Hello Erlang!~n").是start函數(shù)的定義缆娃,io是erlang系統(tǒng)提供的模塊,format是io模塊導(dǎo)出的一個函數(shù)瑰排。因此贯要,Erlang中調(diào)用函數(shù)的基本模式即為<module>:<function>(params).
Getting little sophisticated
Hello Erlang模塊闡述了一個最基本的Erlang模塊,和所有Hello World椭住!程序一樣崇渗,這并沒有什么卵用。我們需要一個更復(fù)雜的程序來展示Erlang的基本編程模式京郑。
%file_server.erl
-module(file_server).
-export([start/1, loop/1]).
start(Dir) ->
spawn(file_server, loop, [Dir]).
loop(Dir) ->
receive
{Client, list_dir} ->
Client ! {self(), file:list_dir(Dir)};
{Client, {get_file, File}} ->
Full = filename:join(Dir, File),
Client ! {self(), file:read_file(Full)};
{Client, {put_file, File, Content}} ->
Full = filename:join(Dir, File),
Client ! {self(), file:write_file(Full, Content)}
end,
loop(Dir).
原子和變量宅广,Erlang中變量以大寫字母開頭,小寫字母開頭的名稱被稱為原子些举,原子不是變量跟狱,而是符號常量,file_server程序中金拒,list_dir兽肤,get_file套腹,put_file都是原子而不是變量绪抛,模塊名也是原子
spawn函數(shù)用于啟動一個進(jìn)程资铡,并返回一個進(jìn)程標(biāo)識符〈甭耄基本模式為spawn(<Module>, <Function>, [params])
self()獲取當(dāng)前進(jìn)程的pid笤休,erlang進(jìn)程間通信依賴于pid
!用于向另一個進(jìn)程發(fā)送消息,Erlang對現(xiàn)實(shí)的建模是通過這種輕量的進(jìn)程間通信實(shí)現(xiàn)的症副,進(jìn)程間交互使用消息店雅。語法為<pid> ! <Message>
-
接收消息,僅僅有發(fā)送消息是不夠的贞铣,還需要接收消息的語法來完成基于消息的進(jìn)程間通信闹啦,接受消息的語法如下。
receive {From ,Message} -> Handle the message
From記錄了消息的來源辕坝,Message是消息本身窍奋,后續(xù)是消息的處理邏輯
-
多種消息的模式匹配,file_server的代碼中可以看見酱畅,receive部分有多種模式琳袄,不同消息會進(jìn)入到不同的處理代碼中,于是這兒的模式是這樣的纺酸。
receive Parttern1 -> Actions1; Parttern2 -> Actions2 %模式之間以;分隔窖逗,最后一種模式后面不能寫;
循環(huán),Erlang是一種函數(shù)是編程語言餐蔬,這意味著其邏輯結(jié)構(gòu)是由一系列的函數(shù)演算構(gòu)成的碎紊,和其他函數(shù)式語言類似,Erlang沒有專門的循環(huán)語法樊诺,因此循環(huán)是通過遞歸實(shí)現(xiàn)的仗考。file_server的代碼中可以看見loop函數(shù)最后遞歸調(diào)用了自己。遞歸代碼總會有遞歸棧占用過大的問題啄骇,編寫成尾遞歸可以借由編譯器的尾遞歸優(yōu)化解決這一問題痴鳄。
上述內(nèi)容已經(jīng)涵蓋了erlang的基本知識,可以繼續(xù)寫出下面的file_client模塊
%file_client.erl
-module(file_client).
-export([ls/1, get_file/2, put_file/3]).
ls(Server) ->
Server ! {self(), list_dir},
receive
{Server, FileList} ->
FileList
end.
get_file(Server, File) ->
Server ! {self(), {get_file, File}},
receive
{Server, Content} ->
Content
end.
put_file(Server, File, Content) ->
Server ! {self(), put_file, File, Content}},
receive
{Server, Result} ->
Result
end.
file_client.el中沒有引入新的內(nèi)容缸夹,在shell中運(yùn)行即可看見運(yùn)行結(jié)果
$ erl
1> c(file_server).
{ok, file_server}
2> c(file_client).
{ok, file_client}
3> FS = file_server:start(".").
<0.45.0> 這是FS這個進(jìn)程的pid
4> file_client:ls(FS).
{ok,["file_client.beam","file_client.erl",
"file_server.beam","file_server.erl","hello.erl"]}
5> file_client:get_file(FS, "hello.erl").
{ok,<<"-module(hello).\n-export([start/0]).\n\nstart() ->\n io:format(\"Hello World!~n\").\n">>}
6> file_client:put_file(FS, "haha", "hehe").
ok
7> file_client:ls(FS).
{ok,["afile_client.beam","afile_client.erl",
"afile_server.beam","afile_server.erl","haha","hello.erl"]}
8> file_client:get_file(FS, "haha").
{ok,<<"hehe">>}
上述的file_server痪寻,file_client,涵蓋了Erlang的基本語法虽惭,模式橡类。下一篇文章會講述Erlang語言在編寫傳統(tǒng)順序程序時的用法。