将记录转换为proplists(和返回)

时间:2010-09-21 12:21:47

标签: erlang

我有一个基于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)}.  

很好的一个小记录,一个有很多大记录的痛苦。任何人都可以建议绕过所有这些样板代码吗?我想我需要一些动态检查记录字段的方法;由于记录是编译时构造,我猜[假设它可能]这意味着通过宏注入代码..

谢谢!

4 个答案:

答案 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