1.04.2014

Getting Started with Erlang pt.5

Erlang をはじめよう その5

 

前回 - mog project: Getting Started with Erlang pt.4 の続き

CHAPTER 9: Exceptions, Errors, and Debugging

 

try .. catch の基本形
> try math:sqrt(-1) of
>   Result -> Result
> catch
>   error: Error -> {error, Error}
> end.
> try math:sqrt(2)
> catch
>   error: Error -> {error, Error}
> end.  % ok
> try math:sqrt(-2)
> catch
>   error: Error -> {error, Error}
> end.
> try
>   X = -2,
>   math:sqrt(X)
> of
>   Result -> Result
> catch
>   error: Error -> {error, Error}
> end.

 

after 節の指定
> F = fun(X) -> try math:sqrt(X)
> catch
>   error: Error -> {error, Error}
> after
>   io:format("AFTER CODE~n")
> end
> end.
> F(2).
> F(-2).

 

例外の送出

エラーと例外を区別することができる。

> throw(my_exception).
> try throw(my_exception)
> catch
>   error: Error -> {found, Error};
>   throw: Exception -> {caught, Exception}
> end.

 

メッセージのロギング
> error_logger:info_msg("information~n").
> error_logger:warning_msg("warning~n").
> error_logger:error_msg("error~n").
> error_logger:info_msg("~p~n", []).
> error_logger:info_report("~p~n", []).    % フォーマットエラーの場合の挙動が異なる

 

ログファイルへの書き込み

カレントディレクトリ配下に test.log というファイルを作成。

> error_logger:logfile({open, "test.log"}).
> error_logger:info_msg("information").
> error_logger:logfile(close).

 

GUI でのデバッグ

debug_info オプションを付けてコンパイルする必要がある。

> c(shop, [debug_info]).
> debugger:start().
  • [GUI操作] Module -> Interrupt... -> デバッグ対象のモジュールを Choose
> Pid1 = spawn(async_shop,async_shop,[]).
  • [GUI操作] Break -> Line Break でブレイクポイントを設置。
> Pid1 ! {apple, 3}.

ステップ実行や、変数の値を確認できた。

 

コンソールでのデバッグ
  • 送受信メッセージのトレース
    > dbg:tracer().
    > Pid1 = spawn(async_shop,async_shop,[]).
    > dbg:p(Pid1,m).
    > Pid1 ! {apple, 3}.
  • 関数呼び出しのトレース
    -module(fact).
    -export([factorial/1]).
    
    factorial(N) -> factorial(1, N, 1).
    
    factorial(Current, N, Result) when Current =< N -> factorial(Current + 1, N, Result * Current);
    factorial(Current, N, Result) -> Result.
    > c(fact).
    > dbg:tracer().
    > dbg:p(all, c).
    > dbg:tpl(fact, factorial, []).
    > fact:factorial(4).

 

CHAPTER10: Storing Structured Data

 

レコード

レコードとは、固定長のデータ構造であり、名前でアクセスすることができるフィールドからなる。
Cの構造体のようなもの。

Erlang におけるレコードはコンパイル時の機能であって、VMに固有の型があるわけではない。

  • レコードの基本操作

    複数のモジュールで共有できるように、レコード定義は個別のファイル(拡張子hrl)に記述するのがよいらしい。

    -record(person, {name, age=20, phone}).
    
    > rr("records.hrl").
    > Person1=#person{}.
    > Person2=#person{name="Alice", age=16}.
    > Person3=#person{name="Bob", phone="123-4567", age=35}.
    > #person{phone=P, name=N} = Person3.
    > {P, N}.
    > Person3 = Person3#person{name="Charlie"}.    % error
    > Person4 = Person3#person{name="Charlie"}.
    > rf().
    > #person{}.
    > Person1.
  • モジュール内でレコードを利用する
    -module(person).
    -export([rename/2]).
    -include("records.hrl").
    
    rename(#person{name=Name} = Person, NewName) ->
      io:format("Changed name: ~s -> ~s~n", [Name, NewName]),
      Person#person{name=NewName}.
    > c(person).
    > rr("records.hrl").
    > P = #person{name="Alice", age=16, phone="123-4567"}.
    > person:rename(P, "Bob").

 

Erlang Term Storage (ETS)

Erlang 付属の KVS (key/value store)。

  • テーブルの作成
    -module(users).
    -export([setup/0]).
    -include("records.hrl").
    
    setup() ->
      Table = ets:new(users, [named_table, {keypos, #person.name}]),
      ets:insert(users, #person{ name="Alice", age=16, phone="123-4567"}),
      ets:insert(users, #person{ name="Bob", age=35, phone="000-0000"}),
      ets:insert(users, #person{ name="Charlie", age=66, phone="111-1111"}),
      ets:info(Table).
    > c(users).
    > users:setup().    % size を確認
    > rr("records.hrl").
    > ets:tab2list(users).
    > tv:start().    % GUI が起動
    > ets:i().

    このような GUI でレコードの内容を確認できる。

    TV ETS users Node nonode nohost
  • レコードの読み込みと更新
    > users:setup().
    > rr("records.hrl").
    > ets:lookup(users, "Alice").
    > ets:lookup(users, "Carol").
    > Alice = hd(ets:lookup(users, "Alice")).
    > ets:insert(users, Alice#person{age=17}).
    > ets:lookup(users, "Alice").

 

Mnesia

分散、並列機能を完全に有した Erlang 付属のDBMS。発音は「エムニージア」でよさそうだ。

  • スキーマ、テーブルの作成
    -module(users).
    -export([setup/0]).
    -include("records.hrl").
    
    setup() ->
      mnesia:create_schema([node()]),
      mnesia:start(),
      mnesia:create_table(person, [{attributes, record_info(fields, person)}]),
    
      F = fun() ->
        mnesia:write(#person{ name="Alice", age=16, phone="123-4567"}),
        mnesia:write(#person{ name="Bob", age=35, phone="000-0000"}),
        mnesia:write(#person{ name="Charlie", age=66, phone="111-1111"})
      end,
    
      mnesia:transaction(F).
    > c(users).
    > rr("records.hrl").
    > users:setup().
    > mnesia:table_info(person, all).
    > tv:start().
  • クエリの実行
    > mnesia:transaction(fun() -> mnesia:read(person, "Alice") end).
    > mnesia:transaction(fun() -> qlc:e(qlc:q( [X || X <- mnesia:table(person)])) end).
    > mnesia:transaction(fun() -> qlc:e(qlc:q(
        [X || X <- mnesia:table(person), X#person.age < 40]
      )) end).
    > mnesia:transaction(fun() -> qlc:e(qlc:q(
        [ {X#person.name, X#person.age} ||
          X <- mnesia:table(person), X#person.age < 40]
      )) end).
    

 

 

 

References

 

Related Posts

0 件のコメント:

コメントを投稿