How do I turn a list of tuple pairs into a record in Erlang?

♀尐吖头ヾ 提交于 2019-12-10 15:54:04

问题


Let's say I have this:

-record(my_record, {foo, bar, baz}).

Keyvalpairs = [{foo, val1},
               {bar, val2},
               {baz, val3}].

Foorecord = #my_record{foo=val1, bar=val2, baz=val3}.

How do I convert Keyvalpairs into Foorecord?


回答1:


The simplest thing to do is:

Foorecord = #my_record{foo=proplists:get_value(foo, Keyvalpairs), 
      bar=proplists:get_value(bar, Keyvalpairs),
      baz=proplists:get_value(baz, Keyvalpairs)}.

If this is too repetitive you can do something like:

Foorecord = list_to_tuple([my_record|[proplists:get_value(X, Keyvalpairs)
      || X <- record_info(fields, my_record)]]).



回答2:


Like the other answers point out, you need to roll your own solution to accomplish this. The solutions proposed are however incomplete. For example, it doesn't take into account default values for record entries. I use the following code snippet to take care of this conversion:

%% @doc returns a "RECSPEC" that can be used by to_rec in order to 
%% perform conversions
-define(RECSPEC(R), {R, tuple_to_list(#R{}), record_info(fields, R)}).

%% @doc converts a property list into a record.
-spec to_rec(recspec(), proplist()) -> record().
to_rec({R, [_ | N], Spec}, P) when is_atom(R) and is_list(Spec) ->
    list_to_tuple(
      [R | lists:foldl(
         fun ({K,V}, A) ->
             case index_of(K, Spec) of
                 undefined -> 
                     A;
                 I -> 
                     {Head, Tail} = lists:split(I, A),
                      Rest = case Tail of
                                [_ | M] -> M;
                                []      -> []
                            end,
                     Head ++ [V | Rest]
             end
         end, N, P)]).

Now one can simply do:

-record(frob, {foo, bar="bar", baz}).

to_rec(?RECSPEC(frob), [{baz, "baz"}, {foo, "foo"}])

which yields

#frob{foo="foo", bar="bar", baz="baz"}

I put this into a little "toolbox" library I am building to collect these little "snippets" that just make life easier when developing Erlang applications: ETBX




回答3:


If you have the values in the same order as in the record, you can convert directly into the record, you just need to precede the name of the record at the first element of the list and then convert the list into a tuple.

Foorecord = list_to_tuple([my_record]++[Val || {_,Val} <- [{foo, val1},{bar, val2},{baz, val3}] ]).


来源:https://stackoverflow.com/questions/873532/how-do-i-turn-a-list-of-tuple-pairs-into-a-record-in-erlang

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!