- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我一直在翻Rage Against The Finite State Machine章的教程,它使用 gen_fsm,它已被弃用而支持 gen_statem。运行测试时,我总是卡住,因为其中一个客户端在 上。协商状态并收到 accept_negotiate 事件 . (也许还有其他错误,但现在我无法弄清楚为什么会发生这种情况)。
trade_statem.erl :
-module(trade_statem).
-behaviour(gen_statem).
% Public API
-export([start/1, start_link/1, trade/2, accept_trade/1, make_offer/2, retract_offer/2, ready/1, cancel/1]).
% gen_statem callbacks
-export([init/1, callback_mode/0, code_change/4, terminate/3]).
% Custom states
-export([idle/3, idle_wait/3, negotiate/3, wait/3, ready/3]).
% Data record
-record(data, {name = "", other, own_items = [], other_items = [], monitor, from}).
% Public API
start(Name) -> gen_statem:start(?MODULE, [Name], []).
start_link(Name) -> gen_statem:start_link(?MODULE, [Name], []).
trade(OwnPid, OtherPid) -> gen_statem:call(OwnPid, {negotiate, OtherPid}, 30000).
accept_trade(OwnPid) -> gen_statem:call(OwnPid, accept_negotiate).
make_offer(OwnPid, Item) -> gen_statem:cast(OwnPid, {make_offer, Item}).
retract_offer(OwnPid, Item) -> gen_statem:cast(OwnPid, {retract_offer, Item}).
ready(OwnPid) -> gen_statem:call(OwnPid, ready, infinity).
cancel(OwnPid) -> gen_statem:stop(OwnPid).
% Client-To-Client API
ask_negotiate(OtherPid, OwnPid) -> gen_statem:cast(OtherPid, {ask_negotiate, OwnPid}).
accept_negotiate(OtherPid, OwnPid) -> gen_statem:cast(OtherPid, {accept_negotiate, OwnPid}).
do_offer(OtherPid, Item) -> gen_statem:cast(OtherPid, {do_offer, Item}).
undo_offer(OtherPid, Item) -> gen_statem:cast(OtherPid, {undo_offer, Item}).
are_you_ready(OtherPid) -> gen_statem:cast(OtherPid, are_you_ready).
not_yet(OtherPid) -> gen_statem:cast(OtherPid, not_yet).
am_ready(OtherPid) -> gen_statem:cast(OtherPid, ready).
ack_trans(OtherPid) -> gen_statem:cast(OtherPid, ack).
ask_commit(OtherPid) -> gen_statem:call(OtherPid, ask_commit).
do_commit(OtherPid) -> gen_statem:call(OtherPid, do_commit).
% gen_statem API
init(Name) -> {ok, idle, #data{name = Name}}.
callback_mode() -> state_functions.
code_change(_, StateName, Data, _) -> {ok, StateName, Data}.
terminate(normal, ready, D = #data{}) -> notice(D, "FSM leaving.", []);
terminate(_, _, _) -> ok.
% Custom states
idle(cast, {ask_negotiate, OtherPid}, D = #data{}) ->
Ref = monitor(process, OtherPid),
notice(D, "~p asked for a trade negotiation", [OtherPid]),
{next_state, idle_wait, D#data{other = OtherPid, monitor = Ref}};
idle({call, From}, {negotiate, OtherPid}, D = #data{}) ->
ask_negotiate(OtherPid, self()),
notice(D, "asking user ~p for a trade", [OtherPid]),
Ref = monitor(process, OtherPid),
{next_state, idle_wait, D#data{other = OtherPid, monitor = Ref, from = From}};
idle(_, Event, _) ->
unexpected(Event, idle),
keep_state_and_data.
idle_wait(cast, {ask_negotiate, OtherPid}, D = #data{other = OtherPid}) ->
gen_statem:reply(D#data.from, ok),
notice(D, "starting negotiation", []),
{next_state, negotiate, D};
idle_wait(cast, {accept_negotiate, OtherPid}, D = #data{other = OtherPid}) ->
accept_negotiate(OtherPid, self()),
notice(D, "accepting negotiation", []),
{next_state, negotiate, D};
idle_wait({call, From}, accept_negotiate, D = #data{other = OtherPid}) ->
accept_negotiate(OtherPid, self()),
notice(D, "accepting negotiation", []),
{next_state, negotiate, D, {reply, From, ok}};
idle_wait(_, Event, _) ->
unexpected(Event, idle_wait),
keep_state_and_data.
negotiate(cast, {make_offer, Item}, D = #data{own_items = OwnItems}) ->
do_offer(D#data.other, Item),
notice(D, "offering ~p", [Item]),
{keep_state, D#data{own_items = add(Item, OwnItems)}};
negotiate(cast, {retract_offer, Item}, D = #data{own_items = OwnItems}) ->
undo_offer(D#data.other, Item),
notice(D, "cancelling offer on ~p", [Item]),
{keep_state, D#data{own_items = remove(Item, OwnItems)}};
negotiate(cast, {do_offer, Item}, D = #data{other_items = OtherItems}) ->
notice(D, "other player offering ~p", [Item]),
{keep_state, D#data{other_items = add(Item, OtherItems)}};
negotiate(cast, {undo_offer, Item}, D = #data{other_items = OtherItems}) ->
notice(D, "Other player cancelling offer on ~p", [Item]),
{keep_state, D#data{other_items = remove(Item, OtherItems)}};
negotiate(cast, are_you_ready, D = #data{other = OtherPid}) ->
io:format("Other user ready to trade~n"),
notice(D, "Other user ready to transfer goods:~nYou get ~p, the other side gets ~p", [D#data.other_items, D#data.own_items]),
not_yet(OtherPid),
keep_state_and_data;
negotiate({call, From}, ready, D = #data{other = OtherPid}) ->
are_you_ready(OtherPid),
notice(D, "asking if ready, waiting", []),
{next_state, wait, D#data{from = From}};
negotiate(EventType, Event, Data) ->
unexpected({EventType, Event, Data}, negotiate),
keep_state_and_data.
wait(cast, are_you_ready, D = #data{}) ->
am_ready(D#data.other),
notice(D, "asked if ready, and I am. Waiting for same reply", []),
keep_state_and_data;
wait(cast, not_yet, D = #data{}) ->
notice(D, "Other not ready yet", []),
keep_state_and_data;
wait(cast, ready, D = #data{}) ->
am_ready(D#data.other),
ack_trans(D#data.other),
gen_statem:reply(D#data.from, ok),
notice(D, "other side is ready. Moving to ready state", []),
{next_state, ready, D};
wait(_, Event, _) ->
unexpected(Event, wait),
keep_state_and_data.
ready({call, _}, ack, D = #data{}) ->
case priority(self(), D#data.other) of
true ->
try
notice(D, "asking for commit", []),
ready_commit = ask_commit(D#data.other),
notice(D, "ordering commit", []),
ok = do_commit(D#data.other),
notice(D, "committing...", []),
commit(D),
% Sus
{stop, normal, D}
catch Class:Reason ->
notice(D, "commit failed", []),
% Sus
{stop, {Class, Reason}, D}
end;
false ->
keep_state_and_data
end;
ready({call, From}, ask_commit, D) ->
notice(D, "replying to ask commit", []),
% Sus
{keep_state_and_data, {reply, From, ready_commit}};
ready({call, _}, do_commit, D) ->
notice(D, "committing...", []),
commit(D),
% Sus
{stop, normal, ok, D};
ready(_, Event, _) ->
unexpected(Event, ready),
keep_state_and_data.
% Private functions
add (Item, Items) -> [Item | Items].
remove(Item, Items) -> Items -- [Item].
notice(#data{name = N}, Str, Args) -> io:format("~s: " ++ Str ++ "~n", [N | Args]).
unexpected(Msg, State) -> io:format("~p received unknown event ~p while in state ~p~n", [self(), Msg, State]).
priority(OwnPid, OtherPid) when OwnPid > OtherPid -> true;
priority(OwnPid, OtherPid) when OwnPid < OtherPid -> false.
commit(D = #data{}) -> io:format("Transaction completed for ~s. Items sent are:~n~p,~n received are:~n~p.~nThis operation should have some atomic save in a database.~n", [D#data.name, D#data.own_items, D#data.other_items]).
trade_calls.erl :
-module(trade_calls).
-export([main_ab/0, main_cd/0, main_ef/0]).
%% test a little bit of everything and also deadlocks on ready state
%% -- leftover messages possible on race conditions on ready state
main_ab() ->
S = self(),
PidCliA = spawn(fun() -> a(S) end),
receive PidA -> PidA end,
spawn(fun() -> b(PidA, PidCliA) end).
a(Parent) ->
{ok, Pid} = trade_statem:start_link("Carl"),
Parent ! Pid,
io:format("Spawned Carl: ~p~n", [Pid]),
%sys:trace(Pid,true),
timer:sleep(800),
trade_statem:accept_trade(Pid),
timer:sleep(400),
io:format("~p~n",[trade_statem:ready(Pid)]),
timer:sleep(1000),
trade_statem:make_offer(Pid, "horse"),
trade_statem:make_offer(Pid, "sword"),
timer:sleep(1000),
io:format("a synchronizing~n"),
sync2(),
trade_statem:ready(Pid),
timer:sleep(200),
trade_statem:ready(Pid),
timer:sleep(1000).
b(PidA, PidCliA) ->
{ok, Pid} = trade_statem:start_link("Jim"),
io:format("Spawned Jim: ~p~n", [Pid]),
%sys:trace(Pid,true),
timer:sleep(500),
trade_statem:trade(Pid, PidA),
trade_statem:make_offer(Pid, "boots"),
timer:sleep(200),
trade_statem:retract_offer(Pid, "boots"),
timer:sleep(500),
trade_statem:make_offer(Pid, "shotgun"),
timer:sleep(1000),
io:format("b synchronizing~n"),
sync1(PidCliA),
trade_statem:make_offer(Pid, "horse"), %% race condition!
trade_statem:ready(Pid),
timer:sleep(200),
timer:sleep(1000).
%% force a race condition on cd trade negotiation
main_cd() ->
S = self(),
PidCliC = spawn(fun() -> c(S) end),
receive PidC -> PidC end,
spawn(fun() -> d(S, PidC, PidCliC) end),
receive PidD -> PidD end,
PidCliC ! PidD.
c(Parent) ->
{ok, Pid} = trade_statem:start_link("Marc"),
Parent ! Pid,
receive PidD -> PidD end,
io:format("Spawned Marc: ~p~n", [Pid]),
%sys:trace(Pid, true),
sync2(),
trade_statem:trade(Pid, PidD),
%% no need to accept_trade thanks to the race condition
timer:sleep(200),
trade_statem:retract_offer(Pid, "car"),
trade_statem:make_offer(Pid, "horse"),
timer:sleep(600),
trade_statem:cancel(Pid),
timer:sleep(1000).
d(Parent, PidC, PidCliC) ->
{ok, Pid} = trade_statem:start_link("Pete"),
Parent ! Pid,
io:format("Spawned Jim: ~p~n", [Pid]),
%sys:trace(Pid,true),
sync1(PidCliC),
trade_statem:trade(Pid, PidC),
%% no need to accept_trade thanks to the race condition
timer:sleep(200),
trade_statem:retract_offer(Pid, "car"),
trade_statem:make_offer(Pid, "manatee"),
timer:sleep(100),
trade_statem:ready(Pid),
timer:sleep(1000).
main_ef() ->
S = self(),
PidCliE = spawn(fun() -> e(S) end),
receive PidE -> PidE end,
spawn(fun() -> f(PidE, PidCliE) end).
e(Parent) ->
{ok, Pid} = trade_statem:start_link("Carl"),
Parent ! Pid,
io:format("Spawned Carl: ~p~n", [Pid]),
%sys:trace(Pid,true),
timer:sleep(800),
trade_statem:accept_trade(Pid),
timer:sleep(400),
io:format("~p~n",[trade_statem:ready(Pid)]),
timer:sleep(1000),
trade_statem:make_offer(Pid, "horse"),
trade_statem:make_offer(Pid, "sword"),
timer:sleep(1000),
io:format("a synchronizing~n"),
sync2(),
trade_statem:ready(Pid),
timer:sleep(200),
trade_statem:ready(Pid),
timer:sleep(1000).
f(PidE, PidCliE) ->
{ok, Pid} = trade_statem:start_link("Jim"),
io:format("Spawned Jim: ~p~n", [Pid]),
%sys:trace(Pid,true),
timer:sleep(500),
trade_statem:trade(Pid, PidE),
trade_statem:make_offer(Pid, "boots"),
timer:sleep(200),
trade_statem:retract_offer(Pid, "boots"),
timer:sleep(500),
trade_statem:make_offer(Pid, "shotgun"),
timer:sleep(1000),
io:format("b synchronizing~n"),
sync1(PidCliE),
trade_statem:make_offer(Pid, "horse"),
timer:sleep(200),
trade_statem:ready(Pid),
timer:sleep(1000).
%%% Utils
sync1(Pid) ->
Pid ! self(),
receive ack -> ok end.
sync2() ->
receive
From -> From ! ack
end.
谢谢你的时间!
最佳答案
有一些错误,您可以运行 diff在他们身上得到差异。您可能会在交易结束时看到一些 otp 报告,但它们完全在意料之中。
trade_statem.erl
-module(trade_statem).
-behaviour(gen_statem).
% Public API
-export([start/1, start_link/1, trade/2, accept_trade/1, make_offer/2, retract_offer/2, ready/1, cancel/1]).
% gen_statem callbacks
-export([init/1, callback_mode/0, code_change/4, terminate/3]).
% Custom states
-export([idle/3, idle_wait/3, negotiate/3, wait/3, ready/3]).
% Data record
-record(data, {name = "", other, own_items = [], other_items = [], monitor, from}).
% Public API
start(Name) -> gen_statem:start(?MODULE, [Name], []).
start_link(Name) -> gen_statem:start_link(?MODULE, [Name], []).
trade(OwnPid, OtherPid) -> gen_statem:call(OwnPid, {negotiate, OtherPid}, 30000).
accept_trade(OwnPid) -> gen_statem:call(OwnPid, accept_negotiate).
make_offer(OwnPid, Item) -> gen_statem:cast(OwnPid, {make_offer, Item}).
retract_offer(OwnPid, Item) -> gen_statem:cast(OwnPid, {retract_offer, Item}).
ready(OwnPid) -> gen_statem:call(OwnPid, ready, infinity).
cancel(OwnPid) -> gen_statem:stop(OwnPid).
% Client-To-Client API
ask_negotiate(OtherPid, OwnPid) -> gen_statem:cast(OtherPid, {ask_negotiate, OwnPid}).
accept_negotiate(OtherPid, OwnPid) -> gen_statem:cast(OtherPid, {accept_negotiate, OwnPid}).
do_offer(OtherPid, Item) -> gen_statem:cast(OtherPid, {do_offer, Item}).
undo_offer(OtherPid, Item) -> gen_statem:cast(OtherPid, {undo_offer, Item}).
are_you_ready(OtherPid) -> gen_statem:cast(OtherPid, are_you_ready).
not_yet(OtherPid) -> gen_statem:cast(OtherPid, not_yet).
am_ready(OtherPid) -> gen_statem:cast(OtherPid, ready).
ack_trans(OtherPid) -> gen_statem:cast(OtherPid, ack).
ask_commit(OtherPid) -> gen_statem:call(OtherPid, ask_commit).
do_commit(OtherPid) -> gen_statem:call(OtherPid, do_commit).
% gen_statem API
init(Name) -> {ok, idle, #data{name = Name}}.
callback_mode() -> state_functions.
code_change(_, StateName, Data, _) -> {ok, StateName, Data}.
terminate(normal, ready, D = #data{}) -> notice(D, "FSM leaving.", []);
terminate(_, _, _) -> ok.
% Custom states
idle(cast, {ask_negotiate, OtherPid}, D = #data{}) ->
Ref = monitor(process, OtherPid),
notice(D, "~p asked for a trade negotiation", [OtherPid]),
{next_state, idle_wait, D#data{other = OtherPid, monitor = Ref}};
idle({call, From}, {negotiate, OtherPid}, D = #data{}) ->
ask_negotiate(OtherPid, self()),
notice(D, "asking user ~p for a trade", [OtherPid]),
Ref = monitor(process, OtherPid),
{next_state, idle_wait, D#data{other = OtherPid, monitor = Ref, from = From}};
idle(_, Event, _) ->
unexpected(Event, idle),
keep_state_and_data.
idle_wait(cast, {ask_negotiate, OtherPid}, D = #data{other = OtherPid}) ->
gen_statem:reply(D#data.from, ok),
notice(D, "starting negotiation", []),
{next_state, negotiate, D};
idle_wait(cast, {accept_negotiate, OtherPid}, D = #data{other = OtherPid}) ->
gen_statem:reply(D#data.from, ok),
notice(D, "starting negotiation", []),
{next_state, negotiate, D};
idle_wait({call, From}, accept_negotiate, D = #data{other = OtherPid}) ->
accept_negotiate(OtherPid, self()),
notice(D, "accepting negotiation", []),
{next_state, negotiate, D, {reply, From, ok}};
idle_wait(_, Event, _) ->
unexpected(Event, idle_wait),
keep_state_and_data.
negotiate(cast, {make_offer, Item}, D = #data{own_items = OwnItems}) ->
do_offer(D#data.other, Item),
notice(D, "offering ~p", [Item]),
{keep_state, D#data{own_items = add(Item, OwnItems)}};
negotiate(cast, {retract_offer, Item}, D = #data{own_items = OwnItems}) ->
undo_offer(D#data.other, Item),
notice(D, "cancelling offer on ~p", [Item]),
{keep_state, D#data{own_items = remove(Item, OwnItems)}};
negotiate(cast, {do_offer, Item}, D = #data{other_items = OtherItems}) ->
notice(D, "other player offering ~p", [Item]),
{keep_state, D#data{other_items = add(Item, OtherItems)}};
negotiate(cast, {undo_offer, Item}, D = #data{other_items = OtherItems}) ->
notice(D, "Other player cancelling offer on ~p", [Item]),
{keep_state, D#data{other_items = remove(Item, OtherItems)}};
negotiate(cast, are_you_ready, D = #data{other = OtherPid}) ->
io:format("Other user ready to trade~n"),
notice(D, "Other user ready to transfer goods:~nYou get ~p, the other side gets ~p", [D#data.other_items, D#data.own_items]),
not_yet(OtherPid),
keep_state_and_data;
negotiate({call, From}, ready, D = #data{other = OtherPid}) ->
are_you_ready(OtherPid),
notice(D, "asking if ready, waiting", []),
{next_state, wait, D#data{from = From}};
negotiate(EventType, Event, Data) ->
unexpected({EventType, Event, Data}, negotiate),
keep_state_and_data.
wait(cast, {do_offer, Item}, D = #data{other_items = OtherItems}) ->
gen_statem:reply(D#data.from, offer_changed),
notice(D, "Other side offering ~p", [Item]),
{next_state, negotiate, D#data{other_items = add(Item, OtherItems)}};
wait(cast, {undo_offer, Item}, D = #data{other_items = OtherItems}) ->
gen_statem:reply(D#data.from, offer_changed),
notice(D, "other side cancelling offer ~p", [Item]),
{next_state, negotiate, D#data{other_items = remove(Item, OtherItems)}};
wait(cast, are_you_ready, D = #data{}) ->
am_ready(D#data.other),
notice(D, "asked if ready, and I am. Waiting for same reply", []),
keep_state_and_data;
wait(cast, not_yet, D = #data{}) ->
notice(D, "Other not ready yet", []),
keep_state_and_data;
wait(cast, ready, D = #data{}) ->
am_ready(D#data.other),
ack_trans(D#data.other),
gen_statem:reply(D#data.from, ok),
notice(D, "other side is ready. Moving to ready state", []),
{next_state, ready, D};
wait(_, Event, _) ->
unexpected(Event, wait),
keep_state_and_data.
ready(cast, ack, D = #data{}) ->
case priority(self(), D#data.other) of
true ->
try
notice(D, "asking for commit", []),
ready_commit = ask_commit(D#data.other),
notice(D, "ordering commit", []),
ok = do_commit(D#data.other),
notice(D, "committing...", []),
commit(D),
% Sus
{stop, normal, D}
catch Class:Reason ->
notice(D, "commit failed", []),
% Sus
{stop, {Class, Reason}, D}
end;
false ->
keep_state_and_data
end;
ready({call, From}, ask_commit, D) ->
notice(D, "replying to ask commit", []),
% Sus
{keep_state_and_data, {reply, From, ready_commit}};
ready({call, _}, do_commit, D) ->
notice(D, "committing...", []),
commit(D),
% Sus
{stop, normal, ok, D};
ready(_, Event, _) ->
unexpected(Event, ready),
keep_state_and_data.
% Private functions
add (Item, Items) -> [Item | Items].
remove(Item, Items) -> Items -- [Item].
notice(#data{name = N}, Str, Args) -> io:format("~s: " ++ Str ++ "~n", [N | Args]).
unexpected(Msg, State) -> io:format("~p received unknown event ~p while in state ~p~n", [self(), Msg, State]).
priority(OwnPid, OtherPid) when OwnPid > OtherPid -> true;
priority(OwnPid, OtherPid) when OwnPid < OtherPid -> false.
commit(D = #data{}) -> io:format("Transaction completed for ~s. Items sent are:~n~p,~n received are:~n~p.~nThis operation should have some atomic save in a database.~n", [D#data.name, D#data.own_items, D#data.other_items]).
关于erlang - 将 Learn You Some Erlang 教程从 gen_fsm 转换为 gen_statem,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67675538/
我想实现一个 Erlang 解释器,最近我在阅读 Erlang 的标准库源代码。我在 erlang.erl 中找到 erlang:display/1 的源代码是: %% display/1 -spec
我即将用 Erlang 构建一个系统(我的问题可以用多个 CPU 更好地解决),我已经浏览了: 向你学习一些 Erlang; Erlang/OTP 在行动 编程 Erlang(阿姆斯壮); Erlan
我真的很难理解 Erlang 中的尾递归。 我有以下 eunit 测试: db_write_many_test() -> Db = db:new(), Db1 = db:write(f
我不确定或者我不知道 erlang 定位不在默认目录中的模块的传统方式。我知道它会查看已编译的文件夹和 erlang 的系统文件夹或 - lists:foreach(fun (E) -> io:fwr
对 Erlang 完全陌生。我正在尝试为函数组合定义一些函数,例如 compose , juxt和 pipe但是遇到这样一个事实,即 Erlang 没有(据我所知)可变参数,因此很难只编写适用于所有输
在 Erlang 中存储和管理高性能可变对象的最佳方法是什么?假设我想编写具有实时游戏玩法的非常简单的在线游戏服务器。不知何故,我需要在 Erlang 内存中表示玩家的状态。例如,它可能只是一个简单的
警告:前面的 erlang n00b。 我正在尝试掌握 erlang,只是尝试与牛仔一起使用基本的 hello world 应用程序。我正在模拟一个错误,基本上是在我的代码中的某处返回一个无效值,并试
当你向 shell 进程发送消息时,你可以通过调用: c:flush(). 来清除所有消息。 C:\Windows\System32>erl Eshell V5.9(使用 ^G 中止) 1> 自我()
这应该是一个简单的问题,但我不太了解文档,无法找到答案。 如果 OTP 管理器在崩溃后重新启动 gen_server,新子进程是否继承了崩溃进程的消息队列,或者消息是否在崩溃之前发送但尚未由旧子进程处
我将 net_ticktime 值设置为 600 秒。 net_kernel:set_net_ticktime(600) 在 net_ticktime = TickTime 的 Erlang 文档中:
我正在监视一个 Erlang 应用程序,我目前正在尝试确定特定 PID 已经运行了多长时间。绝对时间戳或持续时间对我有用,但我在 process_info 或通过 sys 模块看不到这些数据位中的任何
我想重新定义查找特定单词的元组的顺序 例如,我有一个像这样的元组列表: [{"a",["r001"]}, {"bi",["bidder"]}, {"bo",["an"]}] 但有时元组的顺序可能会
以下几行出现在 http://aosabook.org/en/riak.html 中,在该部分的第二段: 15.1. Erlang 简介 : "Calling the function with a
我认为 Erlang 节点之间的消息不应该很大。如果我想构建一个流服务器,通常每个连接都需要很大的带宽,Erlang 能做好吗?如果是,是否有任何开源代码可供我学习?我了解到 Erlang 很适合处理
下一个代码在结果中给了我 5.999999999999998,但正确答案是 6。 Alpha = math:acos((4*4 + 5*5 - 3*3) / (2*4*5)) Area = 1/2 *
注意:这是我的 previous question 的进化延续。关于类似的话题。 一段时间以来,我一直在寻找有关部署和更新 Erlang/OTP 版本(一组应用程序)的“最佳实践”,但我找不到任何直接
我试图在头文件中指定一个函数。 像这样: -spec update(pid(), tuple(tuple(), integer(), atom()), tuple(atom(), atom())) -
所以我在过去的八个小时里一直在使用 Erlang,我花了两个时间用我的头敲击键盘试图找出我的控制台不断返回的异常错误。 我正在编写一个骰子程序来学习erlang。我希望它能够通过 erlang 解释器
当我编译以下模块时: -module(x). -export([inp/0]). f(X) -> g(X). g(X) -> error(X). inp() -> f(123)
我目前正在开发一个实时媒体服务器,它将允许普通消费者向我们发送实时视频。在我们当前的环境中,我们已经看到发送给我们的广播持续了几天,因此能够在不断开用户连接的情况下修复错误(或添加功能)的想法非常引人
我是一名优秀的程序员,十分优秀!