Hatena::Grouperlang

檜山正幸のErlang未確認情報 RSSフィード

2009-03-30 (月)

テストと仕様の融合

| 09:32

EDocとEUnitとナニヤラカニヤラを組み合わせて、最初から「テスト容易=理解容易」なモジュールを書きたいのだが、、、、

2009-03-26 (木)

レコードのデータ型定義

| 14:08

知らない人がいるかもしれないので:

%% @type entry() = #entry{name = atom(),
%%                        args = [string()],
%%                        line = integer(),
%%                        export = bool(),
%%                        data = term()}

-record(entry, {name, args = [], line = 0, export, data}).

なんて書けます。右辺は、レコードを生成するときと同じ構文(憶えやすい)、ただし、値の代わりに型名。

2009-01-14 (水)

helloをちゃんと作る (4) supervisorのスケルトン

| 09:05

とりあえずこんなか。

%% -*- coding: utf-8 -*-

%%% @author Your Name <your.mail.address>
%%% @doc Description
-module(supervisor_skelton).

-behaviour(supervisor).

%% API
-export([start_link/0]).

%% Supervisor callbacks
-export([init/1]).
-export([start_from_shell/0]).

-define(SUP, ?MODULE).

%% @private テスト専用
%% @spec () -> pid()
%% @doc supervisorを起動するが、直後にunlinkする.
%% supervisorプロセスのPIDを返す.
start_from_shell() ->
  {ok, Pid} = start_link(),
  unlink(Pid),
  Pid.

%%====================================================================
%% API functions
%%====================================================================

%% @spec start_link() -> {ok,Pid} | ignore | {error,Error}
%% where
%%   Pid = pid()
%%   Error = term()
%% @doc Starts the supervisor.
start_link() ->
  supervisor:start_link({local, ?SUP}, ?MODULE, []).

%%====================================================================
%% Supervisor callbacks
%%====================================================================

%% @private
%% @spec init(Args::term()) -> Result
%% where
%%  Result = {ok, {{RestartStrategy,MaxR,MaxT}, [ChildSpec]} }
%%         | ignore
%%         | {error, Reason}
%%  RestartStrategy = one_for_all 
%%                  | one_for_one 
%%                  | rest_for_one 
%%                  | simple_one_for_one
%%  MaxR = integer()
%%  MaxT = integer()
%%  ChildSpec = {Id,StartFunc,Restart,Shutdown,Type,Modules}
%%  Id = term()
%%  StartFunc = {M,F,A}
%%  M = atom()
%%  F = atom()
%%  A = [term()]
%%  Restart = permanent | transient | temporary
%%  Shutdown = brutal_kill | integer() | infinity
%%  Type = worker | supervisor
%%  Modules = [Module] | dynamic
%%  Module = atom()

%% @doc Whenever a supervisor is started using 
%% supervisor:start_link/[2,3], this function is called by the new process 
%% to find out about restart strategy, maximum restart frequency and child 
%% specifications.
init([]) ->
  AChild = {'AName',{'AModule',start_link,[]},
            permanent,2000,worker,['AModule']},
  {ok,{{one_for_all,0,1}, [AChild]}}.

%%====================================================================
%% Internal functions
%%====================================================================

%% The End

VoluntasVoluntas2009/02/06 12:46スケルトンステキです。

m-hiyamam-hiyama2009/02/07 16:20Voluntasさん、
お試しください :-)

2008-12-25 (木)

helloをちゃんと作る (2) サーバー

| 08:54

helloをgen_severにした。hello_serverからhello_implを呼んでいる。EDocがちゃんとドキュメントを出すようにした。が、英語と日本語がマゼマゼの事態となった;まっ、いいとしよう。

%% hello_server.erl -*- coding: utf-8 -*-

%% @doc helloアプリケーションサーバー.
-module(hello_server).
-behaviour(gen_server).

-export([ % サーバーの開始
          start_link/0, start/0
        ]).
-export([ % gen_serverのコールバック関数
          init/1, 
          handle_call/3, handle_cast/2, handle_info/2,
          terminate/2, code_change/3
        ]).

-define(SERVER, ?MODULE).

%%====================================================================
%% API
%%====================================================================

%% @doc サーバーをリンクしてスタートさせる.
%% @spec start_link() -> {ok,Pid} | ignore | {error,Error}
%%       where 
%%         Pid = pid()
%%         Error = term()
%%
start_link() ->
  gen_server:start_link({local, ?SERVER}, % サーバーの登録名
                        ?MODULE,          % コールバックモジュール名(アトム)
                        none,             % init/1 への引数
                        []                % オプションリスト
                        ).

%% @doc サーバースタンドアローンでスタートさせる.                       ). 
%% @spec () -> {ok,Pid} | ignore | {error,Error}
start() ->
  gen_server:start({local, ?SERVER}, ?MODULE, none, []).

%%====================================================================
%% gen_server callbacks
%%====================================================================

%% @private
%% @spec init(Args) -> {ok, State} |
%%                     {ok, State, Timeout} |
%%                     ignore |
%%                     {stop, Reason}
%%        where
%%          Args = term()
%%          State = term()
%%          Timeout = integer() | infinity
%%          Reason = term()
%%
%% @doc Initiates the server
init(none) ->
  io:fwrite("Start ~s (~p)~n", [?SERVER, self()]),
  {ok, no_state}. % 状態は使わないのでno_state

%% @private
%% @spec handle_call(Request, From, State) -> {reply, Reply, State} |
%%                                            {reply, Reply, State, Timeout} |
%%                                            {noreply, State} |
%%                                            {noreply, State, Timeout} |
%%                                            {stop, Reason, Reply, State} |
%%                                            {stop, Reason, State}
%%       where
%%         Request = term()
%%         From = {pid(), reference()}
%%         State = #state{}
%%         Timeout = integer() | infinity
%%         Reason = term()
%% 
%% @doc Handling call messages
handle_call(hello, _From, State) ->
  Reply = hello_impl:hello(),
  {reply, Reply, State};
handle_call({hello, Whom}, _From, State) ->
  Reply = hello_impl:hello(Whom),
  {reply, Reply, State};

%% 以下、実験のため;sleep/1, crush/0
handle_call({sleep, MilliSec}, _From, State) ->
  timer:sleep(MilliSec),
  Reply = ok,
  {reply, Reply, State};
handle_call(crush, _From, _State) ->
  erlang:error(crush);
%% その他のcall
handle_call(Request, From, State) ->
  error_logger:warning_msg("unexpected call: call-requet=~p, from=~p~n", 
                            [Request, From]),
  Reply = {error, not_supported},
  {reply, Reply, State}.

%% @private
%% @spec handle_cast(Msg, State) -> {noreply, State} |
%%                                  {noreply, State, Timeout} |
%%                                  {stop, Reason, State}
%%       where
%%         Msg = term()
%%         State = #state{}
%%         Timeout = integer() | infinity
%%         Reason = term()
%%
%% @doc Handling cast messages
handle_cast(stop, State) ->
  {stop, normal, State};
handle_cast(_Msg, State) ->
  error_logger:warning_msg("unexpected cast: cast-messaget=~p~n", 
                            [_Msg]),
  {noreply, State}.

%% @private
%% @spec handle_info(Info, State) -> {noreply, State} |
%%                                   {noreply, State, Timeout} |
%%                                   {stop, Reason, State}
%%       where
%%         Info = term()
%%         State = #state{}
%%         Timeout = integer() | infinity
%%         Reason = term()
%% @doc Handling all non call/cast messages
handle_info(_Info, State) ->
  error_logger:warning_msg("unexpected info: info-messaget=~p~n", 
                            [_Info]),
  {noreply, State}.

%% @private
%% @spec terminate(Reason, State) -> void()
%%       where
%%         Reason = normal | shutdown | term()
%%         State = #state{}
%%
%% @doc This function is called by a gen_server when it is about to
%% terminate. It should be the opposite of Module:init/1 and do any necessary
%% cleaning up. When it returns, the gen_server terminates with Reason.
%% The return value is ignored.
terminate(_Reason, _State) ->
  io:fwrite("Stop ~s (~p)~n", [?SERVER, self()]),
  ok.

%% @private
%% @spec code_change(OldVsn, State, Extra) -> {ok, NewState}
%%       where
%%         OldVsn = term() | {down, term()}
%%         State = #state{}
%%         Extra = term()
%%         NewState = #state{}
%%
%% @doc Convert process state when code is changed
code_change(_OldVsn, State, _Extra) ->
  {ok, State}.

今回使ったスケルトン

%%% -*- coding: utf-8 -*-

%%%-------------------------------------------------------------------
%%% @author Your Name <your@mail.address>
%%% @doc Module Description
%%%
-module(gen_server_edoc_skelton).

-behaviour(gen_server).

%% API
-export([start_link/0]).

%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
         terminate/2, code_change/3]).

%% @type void() = ok | void | none

%% @type state() = #state{}
%%
-record(state, {}).

%%====================================================================
%% API
%%====================================================================

%% @spec start_link() -> {ok,Pid} | ignore | {error,Error}
%%       where 
%%         Pid = pid()
%%         Error = term()
%% 
%% @doc Starts the server
start_link() ->
  gen_server:start_link({local, ?SERVER}, ?MODULE, , ).

%%====================================================================
%% gen_server callbacks
%%====================================================================

%% @private
%% @spec init(Args) -> {ok, State} |
%%                     {ok, State, Timeout} |
%%                     ignore |
%%                     {stop, Reason}
%%        where
%%          Args = term()
%%          State = #state{}
%%          Timeout = integer() | infinity
%%          Reason = term()
%%
%% @doc Initiates the server
init([]) ->
  {ok, #state{}}.

%% @private
%% @spec handle_call(Request, From, State) -> {reply, Reply, State} |
%%                                            {reply, Reply, State, Timeout} |
%%                                            {noreply, State} |
%%                                            {noreply, State, Timeout} |
%%                                            {stop, Reason, Reply, State} |
%%                                            {stop, Reason, State}
%%       where
%%         Request = term()
%%         From = {pid(), reference()}
%%         State = #state{}
%%         Timeout = integer() | infinity
%%         Reason = term()
%% 
%% @doc Handling call messages
handle_call(_Request, _From, State) ->
  Reply = ok,
  {reply, Reply, State}.

%% @private
%% @spec handle_cast(Msg, State) -> {noreply, State} |
%%                                  {noreply, State, Timeout} |
%%                                  {stop, Reason, State}
%%       where
%%         Msg = term()
%%         State = #state{}
%%         Timeout = integer() | infinity
%%         Reason = term()
%%
%% @doc Handling cast messages
handle_cast(_Msg, State) ->
  {noreply, State}.

%% @private
%% @spec handle_info(Info, State) -> {noreply, State} |
%%                                   {noreply, State, Timeout} |
%%                                   {stop, Reason, State}
%%       where
%%         Info = term()
%%         State = #state{}
%%         Timeout = integer() | infinity
%%         Reason = term()
%% @doc Handling all non call/cast messages
handle_info(_Info, State) ->
  {noreply, State}.

%% @private
%% @spec terminate(Reason, State) -> void()
%%       where
%%         Reason = normal | shutdown | term()
%%         State = #state{}
%%
%% @doc This function is called by a gen_server when it is about to
%% terminate. It should be the opposite of Module:init/1 and do any necessary
%% cleaning up. When it returns, the gen_server terminates with Reason.
%% The return value is ignored.
terminate(_Reason, _State) ->
  ok.

%% @private
%% @spec code_change(OldVsn, State, Extra) -> {ok, NewState}
%%       where
%%         OldVsn = term() | {down, term()}
%%         State = #state{}
%%         Extra = term()
%%         NewState = #state{}
%%
%% @doc Convert process state when code is changed
code_change(_OldVsn, State, _Extra) ->
  {ok, State}.

%%--------------------------------------------------------------------
%% Internal functions
%%--------------------------------------------------------------------

%% the end

RianRian2012/10/08 11:58Unbelievable how well-wtirten and informative this was.

rvdafpshahvrvdafpshahv2012/10/09 05:04bTh7lr <a href="http://arcnhmnoyjii.com/">arcnhmnoyjii</a>

milrymqyhoamilrymqyhoa2012/10/09 14:38buCp2o , [url=http://jkemnosbgpsu.com/]jkemnosbgpsu[/url], [link=http://adihidisecpf.com/]adihidisecpf[/link], http://anjyysqtupdt.com/

nffnkgikysnffnkgikys2012/10/10 22:38w4LY0q <a href="http://zbewoilgxxbk.com/">zbewoilgxxbk</a>

jbkrktjbkrkt2012/10/12 02:35qmVN40 , [url=http://gsvebelbjsvg.com/]gsvebelbjsvg[/url], [link=http://ivlknodqlxwf.com/]ivlknodqlxwf[/link], http://qpktraapruqf.com/

2008-12-18 (木)

any()とterm()の心理的な区別

| 14:55

any()とterm()は同義だが:

  • ほんとに何でもよい、任意だ、というときは any()
  • 制約があるんだけど、めんどくさい、あるいは正確には書けないとき term()

って、気持ちのうえでは区別している。

RasadRasad2012/02/09 19:39So much info in so few words. Tosotly could learn a lot.

fttosrpfqrfttosrpfqr2012/02/09 22:04xtmx4I <a href="http://dcwmuvowvxrk.com/">dcwmuvowvxrk</a>

qbwziqzqbwziqz2012/02/11 03:45EuHBqE , [url=http://vmxmmwylocyl.com/]vmxmmwylocyl[/url], [link=http://ewgoxruwespg.com/]ewgoxruwespg[/link], http://oyqkypsxrner.com/

zygmbyzygmby2012/02/12 23:23Gr6C5f <a href="http://foeilrknewxy.com/">foeilrknewxy</a>

iigwhkksnsiigwhkksns2012/02/14 01:05eCy3ac , [url=http://boynrsvpwqyg.com/]boynrsvpwqyg[/url], [link=http://dbgndaxgwozh.com/]dbgndaxgwozh[/link], http://pqhcxmcmdrlj.com/

2008-12-17 (水)

マクロ定数

| 13:12

EDoc内ではマクロ定数(defineした値)が使えないのがけっこう辛い。

そもそも、defineのところにドキュメンテーションコメント書きたいんですけど。

2008-12-16 (火)

マニュアルページにおける記法との異同

| 10:36

マニュアルページでけっこう頻繁に見る void(), int() はEDocの組み込みではない。integer() > 0 (不等式による制約)とか、Foo = 0..10 (範囲)とかも使えない。Minute = Second = integer() のような書き方もダメ。

日付時刻関係

| 10:46

calendarモジュールerlang:now/0 に出てくる型をEDocにも読める形で書いてみた。


%% @type date() = {Year, Month, Day}
%%  Year = integer()
%%  Month = integer()
%%  Day = integer() .
%% 制約: 
%% Month : 1..12, 
%% Day : 1..31

%% @type time() = {Hour, Minute, Second}
%%   Hour = integer()
%%   Minute = integer()
%%   Second = integer() .
%% 制約:
%% Hour : 0..23,
%% Minute, Second : 0..59

%% @type datetime() = {Date, Time}
%%   Date = date()
%%   Time = time()

%% @type day_number() = DayNumber
%%   DayNumber = integer().
%% 制約:
%% DayNumber : 1..7 
%% 1が月曜、7が日曜


%% Now -- see erlang:now/0
%% @type now_value() = {MegaSecs, Secs, MicroSecs}
%%   MegaSecs  = integer()
%%   Secs = integer()
%%   MicroSecs = integer().
%% Unixエポック(00:00 GMT, January 1, 1970)からの経過秒数. 
%% Unixエポックのグレゴリー秒は62167219200(622億弱).

%% @type gregorian_days() = Days
%%   Days = integer().
%% グレゴリー歴0年1月1日からの経過日数.
%% 0年1月1日の経過日数は0 .

%% @type gregorian_seconds() = Seconds
%%   Seconds = integer().
%% グレゴリー歴0年1月1日 0時0分0秒からの経過秒数.

2008-12-15 (月)

はれっ

| 17:07

@argってなかったんかいね。

integerとかしてもエラーにならない。

| 17:07

型名にinteger, stringとしてもアトムと解釈されるだけ。