自分のためのまとめブログ

qlcモジュールで条件を指定する

qlc:q/1,2をだいたいは使う。

 基本的な文法は以下。

[Expression || Qualifier1, Qualifier2, ...]

 -record(test, { x0, x1, x2, x3}).というレコードでデータを保存している場合。
// Aという変数を受けている場合。
qlc:q([ {X#test.x0, X#test.x1, X#test.x3} ||  % ヒットしたデータの何を返すかを指定する
X <- mnesia:table(test),
Y <- mnesia:table(test2),
X#test.x0 > 470,
X#test.x2 =:= Y#test2.x2
]).
 
attributes, recordのフィールドは必須? 

初期設定

mnesia:scheme()

mnesia:create_table 

以下はどれもレコードが必要となる。

データの読み込み


条件付きで使いたい
qlcモジュールを使ってSQLみたいに条件を指定できる
ただし、qlcモジュールを使うためには、qlcのヘッダファイルを以下のようにインクルードする。

-include_lib(

-include_libはC言語の#include <>みたいなもの。
code:lib_dir()で、どこのパスかはわかる。

-includeはC言語の#include ""みたいなもの。

qlc以外にもselectが使えるが、こちらは条件の指定方法がまた違うらしい。
さらに、少ないデータを扱う場合は、selectの方が速度的には有利らしい。

データの書き込み
mnesia:transaction( fun() -> mnesia:write(#record) end).
データの削除 

以下のようにすればできるみたい.

--------------------------------------------------------------- 
conv_str_to_term(String) -> 
{ok, Tokens, _Endline} = erl_scan:string(String ++ "."), 
{ok, AbsForm } = erl_parse:parse_exprs(Tokens), 
{value, Value, _Bs} = erl_eval:exprs(AbsForm, erl_eval:new_bindings()), 
Value. 
--------------------------------------------------------------- 

何やら3回ほど処理をしているが全くなにをやっているかわからない...
ので,調べてみることに.
とりあえず,本家のマニュアルを見てみる.

http://www.erlang.org/doc/man/erl_scan.html#string-1 

まずはそれっぽい文字列を入れてみることに.


1> String = "[{key1,value1},{key2,value2}]".
"[{key1,value1},{key2,value2}]"
2> erl_scan:string(String).
{ok,[{'[',1},
     {'{',1},
     {atom,1,key1},
     {',',1},
     {atom,1,value1},
     {'}',1},
     {',',1},
     {'{',1},
     {atom,1,key2},
     {',',1},
     {atom,1,value2},
     {'}',1},
     {']',1}],
    1}

どうやら意味のある単位で区切っているようだけど,それにくっついている他のはなんだろうか?
※ちなみに,スペースを入れても同じ結果でした

マニュアルを見ると,戻り値については以下のように書かれている.

Return = {ok, Tokens :: tokens(), EndLocation}
       | {error, ErrorInfo :: error_info(), ErrorLocation} 

token is a tuple containing information about syntactic category, the token attributes, and the actual terminal symbol. For punctuation characters (e.g. ;|) and reserved words, the category and the symbol coincide, and the token is represented by a two-tuple. Three-tuples have one of the following forms: {atom, Info, atom()}{char, Info, integer()}{comment, Info, string()}{float, Info, float()}{integer, Info, integer()}{var, Info, atom()}, and {white_space, Info, string()}. 

適当に要約すると,データ型とその値とにわけてくれるらしい.
一緒にくっついている数字は,その文字列があった行数みたい.

試しに以下の通り,複数行の文字列を処理してみると...

1> String = "[{key1,
1> value1}
1> ,
1> {k
1> ey2,value2}
1> ]
1> ".
"[{key1,\nvalue1}\n,\n{k\ney2,value2}\n]\n"
2> erl_scan:string(String).
{ok,[{'[',1},
     {'{',1},
     {atom,1,key1},
     {',',1},
     {atom,2,value1},
     {'}',2},
     {',',3},
     {'{',4},
     {atom,4,k},
     {atom,5,ey2},
     {',',5},
     {atom,5,value2},
     {'}',5},
     {']',6}],
    7}

調子に乗りすぎて改行しまくっていたら,\nも入ってしまっています.
それでも,ちゃんと解析してくれているみたいですが,atomの途中で改行すると当然NGです.

erl_scan:stringについては,この辺にしときたいですが,引数に"."を追加しています.
これは何でしょう?現段階では分からないのでとりあえずパスします.

気を取り直して,次はerl_parse:parse_exprsについてみていきます.

では,以下マニュアルを見てみます.
http://www.erlang.org/doc/man/erl_parse.html#parse_exprs-1 

This function parses Tokens as if it were a list of expressions. 
とあるので,さっき取得した解析結果のリストを渡すと...

1> String = "[{key1,value1},{key2,value2}]".
"[{key1,value1},{key2,value2}]"
2> {ok,Tokens,_Endline}=erl_scan:string(String).
{ok,[{'[',1},
     {'{',1},
     {atom,1,key1},
     {',',1},
     {atom,1,value1},
     {'}',1},
     {',',1},
     {'{',1},
     {atom,1,key2},
     {',',1},
     {atom,1,value2},
     {'}',1},
     {']',1}],
    1}
3> erl_parse:parse_exprs(Tokens).
{error,{1,erl_parse,["syntax error before: ",[]]}}

syntaxエラーとなってしまいました.
そこでさっきまで疑問だった"."を追加してみるとあら不思議!

4> String2 = "[{key1,value1},{key2,value2}].".
"[{key1,value1},{key2,value2}]."
5> {ok,Tokens2,_Endline}=erl_scan:string(String2).
{ok,[{'[',1},
     {'{',1},
     {atom,1,key1},
     {',',1},
     {atom,1,value1},
     {'}',1},
     {',',1},
     {'{',1},
     {atom,1,key2},
     {',',1},
     {atom,1,value2},
     {'}',1},
     {']',1},
     {dot,1}],
    1}
6> erl_parse:parse_exprs(Tokens2).
{ok,[{cons,1,
           {tuple,1,[{atom,1,key1},{atom,1,value1}]},
           {cons,1,
                 {tuple,1,[{atom,1,key2},{atom,1,value2}]},
                 {nil,1}}}]}

成功しました!
"."は必要みたいです.
たぶんErlangのソースを動的に解析して何かをしたいというときに,こういうことするんでしょうね...

次回この結果について見ていきます.

 

このページのトップヘ