tags:

views:

60

answers:

2

I'd like to create a record from a list of attributes - not the actual proplist, but for example from #xmlElement attributes. I've got a list of elements which I need to process and a list of possible attributes.

I could of course do something like:

create_record(Rec, [{attr1, Val}|As]) -> create_record(Rec#blah{attr1 = Val}, As);
create_record(Rec, [{attr2, Val}|As]) -> create_record(Rec#blah{attr2 = Val}, As);
...

But that's going to be a bit long and I already have the list of possible attributes (I could even use record_info(fields, blah). I see a lot of crazy ways to do it with accessing the actual record tuple with setelement, but maybe there's a simpler solution?

+2  A: 

I'd probably be most tempted by:

create_record(Lst) ->
     #blah{
         attr1=proplists:get_value(attr1, Lst, default_attr1),
         attr2=proplists:get_value(attr2, Lst, default_attr2),
         ...
     }.

The point of transforming this thing into a record is probably to get static checking of attributes at compile time elsewhere in your code, so I don't think there's any harm in being straightforward and a little repetitive here.

If you do want to, the record_info magic is pretty straightforward, but remember record_info isn't a real function so this function can't be generic. (A macro could be.)

make_record(Lst) ->
    list_to_tuple([blah|[proplists:get_value(X, Lst) || X <- record_info(fields, blah)]]).

If you really want dynamic keys at runtime, then use a dict.

cthulahoops
+2  A: 

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.

Roberto Aloi