我有一个基于Mochiweb和Mnesia的Erlang webapp,它使用和发出JSON。将记录存储在Mnesia中是有意义的;但是Mochiweb / Mochijson需要采用proplist格式的数据。所以我最终得到了大量的样板代码:
-record(foobar, {name, value}).
record_to_proplist(Record)->
[{name, Record#foobar.name},
{value, Record#foobar.value}].
proplist_to_record(Props)->
#foobar{name=proplists:get_value("name", Props),
value=proplists:get_value("value", Props)}.
很好的一个小记录,一个有很多大记录的痛苦。任何人都可以建议绕过所有这些样板代码吗?我想我需要一些动态检查记录字段的方法;由于记录是编译时构造,我猜[假设它可能]这意味着通过宏注入代码..
谢谢!
答案 0 :(得分:22)
您应该可以执行以下操作:
-record(foobar, {name, value}).
-record(foo, {other, fields, 'and', stuff}).
record_to_proplist(#foobar{} = Rec) ->
lists:zip(record_info(fields, foobar), tl(tuple_to_list(Rec)));
record_to_proplist(#foo{} = Rec) ->
lists:zip(record_info(fields, foo), tl(tuple_to_list(Rec))).
等
(或者作为一个宏(仍在创建一个函数,宏的版本是什么?R2P(Rec,foobar)太丑了):
-define(R2P(Record), record_to_proplist(#Record{} = Rec) ->
lists:zip(record_info(fields, Record), tl(tuple_to_list(Rec)))).
?R2P(foobar);
?R2P(foo).
)
答案 1 :(得分:2)
使用record_info(fields,foobar)可以动态地执行某些操作。然而,record_info也是一个编译时构造,因此记录名不能是变量,因此您需要为要转换的每个记录使用一个子句。
答案 2 :(得分:1)
听起来像exprecs就是你要找的东西:
http://forum.trapexit.org/viewtopic.php?p=21790
阅读说明:
该模块是一个解析变换 允许您导出记录。该 transform为其添加了访问器功能 实例化,检查和 修改记录,而不必 介绍编译时依赖项 模块之间。
看看这是否有帮助。
答案 3 :(得分:0)
接受的答案中的链接已经很久了。
简短的回答是使用Ulf Wiger的exprecs。
exprecs是uwiger/parse_trans
中的parse_transform有关其工作原理的文章存档于以下网址:http://web.archive.org/web/20130729014934/http://forum.trapexit.org/viewtopic.php?p=21790