erlang每日练手--4

本文展示了Erlang中实现简单消息响应服务器、进程环以及二分查找的功能。通过`echo/0`函数创建响应服务器,`procRing/3`实现进程间消息传递,`binary_search/2`进行二分查找。示例代码详细解释了各个功能的实现逻辑。
摘要由CSDN通过智能技术生成
-module(daily_four).

-export([echo/0]).
-export([start1/0, start2/0]).
-export([procRing/3]).
-export([binary_search/2]).


%% ==========================================================
%% 简单的消息响应服务器
%% ==========================================================
echo()	->
	register(echo, spawn(fun() -> loop() end)).

loop()	->
	receive
		stop -> 
			io:format("echo server closed!~n");
		Msg	-> 
			io:format("echo server received:~p~n", [Msg]),
			loop()
	end.

print(Msg)	->	echo ! Msg.

stop()	->	echo ! stop.


%% ===================================================
%% 编译时会报警告,调用时不会输出任何信息
%% ===================================================
% start() -> spawn(fun() -> loop() end).

% loop() ->
% 	receive
% 		{rectangle, Width, Height}	->
% 			Width*Height;
% 		{circle, Radius}	->
% 			3.14 * Radius * Radius
% 	end,
% 	loop().

%% ===================================================
%% 调用时会输出消息本身
%% 输入:
%%	Pid = demo2:start1().
%%	Pid ! {circle, 5}.
%% 输出:
%%	Result:78.5
%%	{circle, 5}
%% ===================================================
start1() -> spawn(fun() -> loop1() end).

loop1() ->
	receive
		{rectangle, Width, Height}	->
			io:format("Result:~p~n", [Width*Height]);
		{circle, Radius}	->
			io:format("Result:~p~n", [3.14 * Radius * Radius])
	end,
	loop1().

%% ===================================================
%% 调用时不会输出消息本身
%% 输入:
%%	Pid = demo2:start2().
%%	demo2:rpc(Pid, {circle, 5}).
%% 输出:
%%	78.5
%% 说明:
%% 不太清楚为什么这里就不输出信息本身??????
%% ===================================================
start2() -> spawn(fun() -> loop2() end).

rpc(Pid, Request)	->		%% 此函数的作用仅仅只是为了调用loop函数时传递From参数
	Pid ! {self(), Request},
	receive
		Response	-> Response
	end.

loop2()	->
	receive
		{From, {rectangle, Width, Height}}	->	
			From ! Width * Height;
		{From, {circle, Radio}}	-> 
			From ! 3.14 * Radio * Radio;
		{From, Other}	-> 
			From ! {error, Other}
	end,
	loop2().


%% =====================================================
%% 进程环
%% 创建ProcNum个进程,这ProcNum个进程组成一个进程环,然后将Message沿着进程环传送SendNum次
%% =====================================================
procRing(ProcNum, SendNum, Message)	->
	processes(ProcNum, ProcNum),
	io:format("==========================================~n"),
	sendMessage(1, SendNum, Message, ProcNum).

processes(N, Max)	->
	for(N, fun(X) -> genProcess(X, Max) end).

for(1, F)	-> [F(1)];
for(N, F)	-> [F(N) | for(N - 1, F)].
	
genProcess(N, Max)	->
	ProN = genAtom(N),
	register(ProN, spawn(fun() -> loopRing(Max) end)),
	io:format("Process [~p:~p] was created successfully!~n", [ProN, whereis(ProN)]).

% process name
genAtom(N)	->
	L = lists:concat([proc_, N]),
	list_to_atom(L).

loopRing(Max)	->
	receive
		die ->	quit;
		{From, {X, Y, Z}}	-> 
			io:format("Message [~p] from (~p) to (~p)~n", [Z, From, self()]),
			sendMessage(X + 1, Y, Z, Max),
			loopRing(Max);
		Other	->
			io:format("Other:~p~n", [Other])
	end.

sendMessage(CurProcIndex, SendNum, Message, MaxProcIndex)	->
	if
		CurProcIndex =:= 1 ->					% 如果是第一次发,则必须从最后面一个进程发送到第一个进程
			Pid1 = whereis(genAtom(MaxProcIndex)),
			Pid2 = whereis(genAtom(CurProcIndex));
		CurProcIndex =/= 1 ->					% 如果不是第一次发,则是前一个进程发送到当前进程
			Pid1 = whereis(genAtom(CurProcIndex - 1)),
			Pid2 = whereis(genAtom(CurProcIndex))
	end,
	if
		SendNum =:= 0 ->
			quit;
		SendNum =/= 0 ->
			Pid2 ! {Pid1, {CurProcIndex, SendNum - 1, Message}}
	end.


%% ======================================================
%% binary search
%% ======================================================
binary_search(N, L) -> do_search(N, L).


do_search(N, [])	-> 
	io:format("~p is not exist in list~n", [N]);
do_search(N, L)	-> 
	MidValue = mid_value(L),
	if
		MidValue =:= N ->
			io:format("Successfully,~n");
		MidValue > N	->
			HalfList = [X || X <- L, X < MidValue],
			do_search(N, HalfList);
		MidValue < N 	->
			HalfList = [X || X <- L, X > MidValue],
			do_search(N, HalfList)
	end.

% 获取列表长度
len([])	-> 0;
len([_H|T])	-> 1 + len(T).

% 获取列表中指定序号的项
get(1, [H|_T])	-> H;
get(N, [_H|T])	-> get(N - 1, T).

% 获取列表中中间位置的项
mid_value(L)	->
	Len = len(L),
	Index = Len div 2,
	if
		Index =:= 0	->
			get(1, L);
		Index =/= 0	->
			get(Index, L)
	end.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值