前生

一年前,我写了篇浅谈游戏配置数据在erlang使用,一年后,我在同事的提示下,我又简化实现,甚至可以无限扩展了,原先拼字符串会有种种局限性。

原理

本质上,配置数据转代码而已,然后可以将数据用erl_syntax的接口表示成代码的AST,接着用format接口转化成具体的代码。这中间使用到了erlang的AST,理论上,你想生成什么样的erlang代码都可以,毕竟erl_syntax是一个erlang完备的语法树。

example

这里只是实验性代码,具体完备功能就按照各位具体项目需求去各自实现吧,有疑问可以发email找我探讨下。

-module(erl_syntax_try).
-compile(export_all).
test() ->
    RecordName = erl_syntax:atom(base_dungeon),
    erl_syntax:record_expr(RecordName, [
                                        erl_syntax:record_field(erl_syntax:atom(key0), erl_syntax:abstract(1)),
                                        erl_syntax:record_field(erl_syntax:atom(key1), erl_syntax:abstract(atom)),
                                        erl_syntax:record_field(erl_syntax:atom(key2), erl_syntax:abstract("xxx")),
                                        erl_syntax:record_field(erl_syntax:atom(key3), erl_syntax:abstract(<<"hello中文"/utf8>>)),
                                        erl_syntax:record_field(erl_syntax:atom(key3), 
                                                                erl_syntax:binary([erl_syntax:binary_field(
                                                                                     erl_syntax:string("hello中文"),
                                                                                     [erl_syntax:atom(utf8)]
                                                                                    )])
                                                               )
                                      ]).

write() ->
    file:write_file("/tmp/1.erl", [unicode:characters_to_binary(erl_prettypr:format(test()))]).

format() ->
    io:format("~w~n", [erl_prettypr:format(test())]).

生成的代码长这样

#base_dungeon{key0 = 1, key1 = atom, key2 = "xxx",
              key3 =
                  <<104, 101, 108, 108, 111, 228, 184, 173, 230, 150,
                    135>>,
                    key3 = <<"hello中文"/utf8>>}

最后,加个函数什么就可以了。

我们项目的生成的代码例子如下 %% version : 002a4bbf4625aa6234ae8c8cdc170417 %% Warning:本文件由data_generate自动生成,请不要手动修改

-module(data_base_treasure_award).

-export([get/1]).

-include("db_base_treasure_award.hrl").

get(1) ->
    #base_treasure_award{id = 1, item_id = 20001,
             award_count = 1};
get(2) ->
    #base_treasure_award{id = 2, item_id = 20002,
             award_count = 1};
get(3) ->
    #base_treasure_award{id = 3, item_id = 20003,
             award_count = 1};
get(4) ->
    #base_treasure_award{id = 4, item_id = 20004,
             award_count = 1};
get(5) ->
    #base_treasure_award{id = 5, item_id = 0,
             award_count = 1};
get(6) ->
    #base_treasure_award{id = 6, item_id = 3,
             award_count = 1};
get(7) ->
    #base_treasure_award{id = 7, item_id = 1,
             award_count = 1};
get(8) ->
    #base_treasure_award{id = 8, item_id = 1,
             award_count = 2};
get(9) ->
    #base_treasure_award{id = 9, item_id = 1,
             award_count = 3};
get(10) ->
    #base_treasure_award{id = 10, item_id = 2,
             award_count = 100};
get(11) ->
    #base_treasure_award{id = 11, item_id = 2,
             award_count = 500};
get(12) ->
    #base_treasure_award{id = 12, item_id = 2,
             award_count = 1000};
get(13) ->
    #base_treasure_award{id = 13, item_id = 25009,
             award_count = 1};
get(Val) -> lager:warning("get not find ~p", [Val]), [].

最后

这仅仅是个data2code的一个思路,欢迎交流。