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 でレコードの内容を確認できる。
- レコードの読み込みと更新
> 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
0 件のコメント:
コメントを投稿