讓我們仔細看看這一點。 「rpc」是什麼意思? 「遠程過程調用」 - 當然。但是在Erlang的一切是一個rpc,所以我們傾向於不使用這個術語。相反,我們區分同步消息(呼叫者阻止,等待響應)和異步消息(呼叫者只需觸發消息並在世界中無需關心的情況下運行)。我們傾向於使用術語「呼叫」來表示同步消息,而使用「施放」表示異步消息。
我們可以很容易地編寫,因爲調用看起來很像上面的rpc,在Erlang中增加了一個獨特的參考值來標記消息並監視我們發送消息的過程,以防萬一它崩潰(所以我們沒有得到左邊掛,等待永遠不會到來的迴應......我們將在一點觸摸你的代碼):
% Synchronous handler
call(Proc, Request) ->
Ref = monitor(process, Proc),
Proc ! {self(), Ref, Request},
receive
{Ref, Res} ->
demonitor(Ref, [flush]),
Res;
{'DOWN', Ref, process, Proc, Reason} ->
{fail, Reason}
after 1000 ->
demonitor(Ref, [flush]),
{fail, timeout}
end.
Cast是更容易一點:
cast(Proc, Message) ->
Proc ! Message,
ok.
以上調用的定義意味着我們發送給的進程將接收一條形式爲{SenderPID, Reference, Message}
的消息。請注意,這是不同比{sender, reference, message}
,因爲小寫字母值爲atoms,這意味着它們是它們自己的值。
當我們receive
消息我們是匹配關於接收到的消息的形狀和值。這意味着,如果我有
receive
{number, X} ->
do_stuff(X)
end
在我的代碼
,它不會匹配過程坐在那receive
得到一個消息{blah, 25}
。如果它收到另一個消息{number, 26}
那麼它將匹配,即receive
將調用do_stuff/1
並且該過程將繼續。 (這兩件事 - atoms
和Variables
之間的區別與receive
作品中的匹配方式 - 是您的代碼掛起的原因。)初始郵件{blah, 25}
仍將位於郵箱中,但位於隊列的前端,所以下一個receive
有機會匹配它。郵箱的這個屬性有時非常有用。
但是,什麼是一個全部看起來像?
高於你期望三種消息:
{insert, Key, Value}
{retrieve, Key}
stop
你穿起來有所不同,但是這是你想什麼營業結束去做。通過我在上面寫到的call/2
函數運行插入消息將會看起來像這樣:{From, Ref, {insert, Key, Value}}
。所以,如果我們期望從進程的接收循環中得到任何響應,我們需要按照確切的形式進行匹配。我們如何捕捉意外消息或形成不良的消息?在receive
條款的最後,我們可以把一個赤裸裸的變量,以匹配任何其他:
loop(State) ->
receive
{From, Ref, {insert, Key, Value}} ->
NewState = insert(Key, Value, State),
From ! {Ref, ok},
loop(NewState);
{From, Ref, {retrieve, Key}} ->
Value = retrieve(Key, State),
From ! {Ref, {ok, Value}},
loop(State);
{From, Ref, stop} ->
ok = io:format("~tp: ~tp told me to stop!~n", [self(), From]),
From ! {Ref, shutting_down},
exit(normal)
Unexpected ->
ok = io:format("~tp: Received unexpected message: ~tp~n",
[self(), Unexpected]),
loop(State)
end.
你會發現,我不使用進程字典。不要使用過程字典。這不是它的目的。你會覆蓋重要的東西。或者丟掉重要的東西。或者......呃,不要這樣做。使用字典或映射或gb_tree或其他代替,並將其作爲過程'State
變量傳遞。一旦你稍後開始編寫OTP代碼,這對你來說將變得非常自然。
玩弄這些東西,你很快就會高興地發送垃圾郵件到你的程序死亡。
第一個問題,在你走之前:Erlang *沒有類或方法*。一切都是功能。每個函數都會返回一個值。雖然有[*進程*,而不是*類*](http://stackoverflow.com/questions/32294367/erlang-process-vs-java-thread/32296577#32296577),你可以發送*消息* ,但他們如何迴應這些問題的方式與方法完全不同。 – zxq9
謝謝。你是對的。我仍然不明白Erlang的一切工作原理 –