レコードとマクロ
Getting Started With Erlangの5章。「5.3 Records」と「5.4 Macros」
レコード
レコードは名前付きのタプル定義です。これを使うと名前と値を指定してタプルを生成できます。
- 名前付きなので順番を考慮せずにタプルが作成できます。
- データの追加が比較的簡単にできます。追加したデータは初期値がundefinedのアトムとなります。データを追加しても、それを使っていないところのコードは修正不要です。
「-record」で定義してから利用します。形式は次の通り。
-record(<レコード名>,{<フィールド名1>, <フィールド名2>, ...}).
使うときは次のようにします。
#<レコード名>{<フィールド名1>=<値1>, <フィールド名2>=<値2>)
これは次のタプルと同じです。タプルの先頭には「<レコード名>」がつきます(で、何がうれしいのかは不明。)。
{<レコード名>, <値1>, <値2>}
レコードのサンプル。
-module(record). -export([test/2, test2/1]). % レコードの定義 -record( kitten, { age, name, type } ). test(Age,Name) -> % レコードを使うと順番に左右されずにタプルを作成できる。 Kitten = #kitten{name=Name,age=Age, type=mike}, io:format( "~w~n", [Kitten] ), % 値が指定されなかった場合、undefinedのタプルになる。 Kitten2 = #kitten{name=Name}, io:format( "~w~n", [Kitten2] ). test2( K ) -> % パターンマッチでも使える。 case K of #kitten{age=1, name=Name} -> io:format( "~w is 1 year old. ~n", [Name] ); #kitten{age=2, name=Name} -> io:format( "~w is 2 year old. ~n", [Name] ); #kitten{name=Name} -> io:format( "~w is over 2 year old. ~n", [Name] ) end.
実行結果です。
9> record:test(10,mii). {kitten,10,mii,mike} {kitten,undefined,mii,undefined} ok 10> record:test2({kitten,10,mii,mike}). mii is over 2 year old. ok 11> record:test2({kitten,1,mii,mike}). mii is 1 year old. ok 12> record:test2({kitten,2,mii,mike}). mii is 2 year old. ok
マクロ
マクロは置換文字列の指定です。
-define(<名前>, <値>).
としておくと、コード中の
?<名前>
が「<値>」に置き換わります。
サンプルです。
% マクロの定義 -define(a, macro). -define(b, Data). -define(c, ?a(X, Y) -> io:format( "~w, ~w~n", [X,Y] )). % ?a, ?b, ?cはマクロの値に置き換わる。 -module(?a). -export([?a/1, ?a/2]). ?a(?b) -> io:format( "~w~n", [?b] ). ?c . % まじか!
実行結果です。
41> c(macro). {ok,macro} 42> macro:macro(test). test ok 43> macro:macro(test, foo). test, foo ok
コンパイル前の単純な文字列置換っぽいなー。無茶できそう。JavaとかRubyとかJavaScriptにはない機能なのでちょっと新鮮でした。