Dynamic Erlang动态记录编辑

Dynamic Erlang动态记录编辑,dynamic,erlang,record,Dynamic,Erlang,Record,我正在mnesia中存储一些数据,我希望能够更改大部分涉及的值 天真的 change(RecordId, Slot, NewValue) -> [Rec] = do(qlc:q([X || X <- mnesia:table(rec), X#rec.id =:= RecordId])), NewRec = Rec#rec{Slot=NewValue}, F = fun() -> mnesia:write(NewRec) end, {atomic,

我正在
mnesia
中存储一些数据,我希望能够更改大部分涉及的值

天真的

change(RecordId, Slot, NewValue) ->
    [Rec] = do(qlc:q([X || X <- mnesia:table(rec), X#rec.id =:= RecordId])),
    NewRec = Rec#rec{Slot=NewValue},
    F = fun() -> mnesia:write(NewRec) end,
    {atomic, Val} = mnesia:transaction(F),
    Val.

但是仍然有一些代码重复。有没有办法把这种模式抽象出来?是否存在允许编辑记录的既定技术?一般来说有什么想法吗?

因为记录是由元组表示的,所以可以尝试使用元组操作来设置单个值

-module(rec).
-export([field_num/1, make_rec/0, set_field/3]).
-record(rec, {slot1, slot2, slot3}).

make_rec() ->
  #rec{slot1=1, slot2=2, slot3=3}.

field_num(Field) ->
  Fields = record_info(fields, rec),
  DifField = fun (FieldName) -> Field /= FieldName end,
  case length(lists:takewhile(DifField, Fields)) of
    Length when Length =:= length(Fields) ->
      {error, not_found};
    Length ->
      Length + 2
  end.

set_field(Field, Value, Record) ->
  setelement(field_num(Field), Record, Value).
set_字段将返回更新的记录:

Eshell V5.9.1  (abort with ^G)
1> c(rec).
{ok,rec}
2> A = rec:make_rec().
{rec,1,2,3}
3> B = rec:set_field(slot3, other_value, A).
{rec,1,2,other_value}

您还可以将
change
定义为宏(尤其是仅在模块内部使用时):


使用宏,您还可以将
\uuuuu
作为字段传递(有利于模式匹配)。

使用记录实际上是元组的另一种方法是:

change(RecordId, Index, NewValue) ->
    [Rec] = do(qlc:q([X || X <- mnesia:table(rec), X#rec.id =:= RecordId])),
    NewRec = setelement(Index, Rec, NewValue),
    F = fun() -> mnesia:write(NewRec) end,
    {atomic, Val} = mnesia:transaction(F),
    Val.

这也是将记录作为元组的“干净”使用,因为您正在使用
#rec.name
语法查找元组中字段的索引。这就是添加此语法的原因。

请参阅中的第9.8节“记录的内部表示”。字段名仅在编译时可用,因此不能在#rec语法中为字段名使用变量。record_info()函数可能会对您尝试执行的操作有所帮助。我最终执行了类似的操作。作为对阅读该问题的人的一个提示,这里也很有用。
-define(change(RecordId, Slot, NewValue),
        begin
            [Rec] = do(qlc:q([X || X <- mnesia:table(rec), X#rec.id =:= RecordId])),
            NewRec = Rec#rec{Slot=NewValue},
            F = fun() -> mnesia:write(NewRec) end,
            {atomic, Val} = mnesia:transaction(F),
            Val
        end).
test(R, Id) ->
    ?change(Id, name, 5).
change(RecordId, Index, NewValue) ->
    [Rec] = do(qlc:q([X || X <- mnesia:table(rec), X#rec.id =:= RecordId])),
    NewRec = setelement(Index, Rec, NewValue),
    F = fun() -> mnesia:write(NewRec) end,
    {atomic, Val} = mnesia:transaction(F),
    Val.
5> Val = record:change(id58, #rec.name, new_value).