开发者

Converting records to proplists (and back)

开发者 https://www.devze.com 2023-01-17 12:04 出处:网络
I have a Erlang webapp, based on Mochiweb and Mnesia, which consumes and emits JSON. It makes sense to store records in Mnesia; however Mochiweb/Mochijson require data in proplist format. So I end up

I have a Erlang webapp, based on Mochiweb and Mnesia, which consumes and emits JSON. It makes sense to store records in Mnesia; however Mochiweb/Mochijson require data in proplist format. So I end up with a large amount of boilerplate code:

-record(foobar, {name, value}).

record_to_proplist(Record)-&g开发者_运维技巧t;  
  [{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)}.  

Fine with a single small record, a pain with lots of large records. Can anyone suggest a way round all this boilerplate code ? I guess I need some way of inspecting a record's fields dynamically; and since records are a compile-time construct, I'm guessing [assuming it's possible] this means injecting code via a macro ..

Thanks!


You should be able to do something like:

-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))).

Etc.

(Or as a macro (still creating a function though, the version where the macro is ?R2P(Rec, foobar) is just too ugly):

-define(R2P(Record), record_to_proplist(#Record{} = Rec) ->
           lists:zip(record_info(fields, Record), tl(tuple_to_list(Rec)))).

?R2P(foobar);
?R2P(foo).

)


It sounds like exprecs is what you're looking for:

http://forum.trapexit.org/viewtopic.php?p=21790

Reading from the description:

The module is a parse transform allowing you to export records. The transform adds accessor functions for instantiating, inspecting and modifying records, without having to introduce compile-time dependencies between modules.

See if this helps.


Using record_info(fields, foobar) it is possible to do something dynamically. record_info however is also a compile time construct so the record name cannot be a variable, so you need one clause for each record you intend to convert.


The link in the accepted answer for this has been long dead.

The short answer is to use exprecs from Ulf Wiger.

exprecs is a parse_transform in uwiger/parse_trans

The article on how this works is archived in the web archive at: http://web.archive.org/web/20130729014934/http://forum.trapexit.org/viewtopic.php?p=21790

0

精彩评论

暂无评论...
验证码 换一张
取 消