erlang #1 素数リストを求めるでつくったサーバを"Erlang World gen_server"を参考にしてgen_server化してみる。
init()の使い方がイマイチわからないまま。
# cat gprime.erl -module(gprime). -behaviour(gen_server). -export([start/0]). -export([get/1, check/1]). -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). -compile(export_all). start() -> gen_server:start_link({local, ?MODULE}, ?MODULE,args,[]). init(_Args) -> Checked = 2, PrimeList = [2], {ok, {Checked, PrimeList}}. get(N) -> gen_server:call(?MODULE, {getlist, N}). check(N) -> gen_server:call(?MODULE, {checkprime, N}). handle_call({getlist, N}, _From, {Checked, PrimeList}) -> Ret = getl(N, Checked, PrimeList), {reply, Ret, {max(Checked, N), largeList(Ret, PrimeList)} }; handle_call({checkprime, N}, _From, {Checked, PrimeList}) -> Ret = getl(N, Checked, PrimeList), {reply, (lists:last(Ret) =:= N), {max(Checked, N), largeList(Ret, PrimeList)} }. handle_cast(_Msg, State) -> {noreply, State}. handle_info(_Info, State) -> {noreply, State}. terminate(_Reason, _State) -> ok. code_change(_OldVsn, State, _Extra) -> {ok, State}. %% Nまでの素数リストを返す getl(1, _, _) -> []; getl(N, Checked, PrimeList) -> if N =< Checked -> %% すでに求めた素数リストPrimeListから返す lists:filter(fun(X) -> X =< N end, PrimeList); true -> %% すでに求めた素数リストに、Nまでの整数リストを追加 prime(trunc(math:sqrt(N)), [], PrimeList ++ lists:seq(Checked,N)) end. %% prime(Max:最大実行回数、P:素数リスト、[H|T]:2からNまでの整数のリスト) prime(Max, P, [H|T]) -> if H > Max -> P ++ [H|T]; true -> prime(Max, P ++ [H],lists:filter(fun(X) -> (X rem H) =/= 0 end, T)) end. largeList(L1, L2) -> if (length(L1) < length(L2)) -> L2; true -> L2 end.
実行方法は以下。
# erl Erlang R16B02 (erts-5.10.3) [source] [smp:2:2] [async-threads:10] [hipe] [kernel-poll:false] Eshell V5.10.3 (abort with ^G) 1> gprime:start(). {ok,<0.34.0>} 2> gprime:get(10). [2,3,5,7] 3> gprime:get(100). [2,11,13,15,17,19,21,23,25,27,29,31,33,35,37,39,41,43,45,47, 49,51,53,55,57,59,61,63,65|...] 4>