让我们说我有一个记录:
-record(foo, {bar}).
Run Code Online (Sandbox Code Playgroud)
我想要做的是能够将记录名称作为参数传递给函数,并获取新记录.该函数应该是通用的,以便它应该能够接受任何记录,如下所示.
make_record(foo, [bar], ["xyz"])
Run Code Online (Sandbox Code Playgroud)
实现这样的功能时我试过这个:
make_record(RecordName, Fields, Values) ->
NewRecord = #RecordName{} %% this line gives me an error: syntax error before RecordName
Run Code Online (Sandbox Code Playgroud)
是否可以将记录名称用作参数?
如果在编译期间无权访问记录,则无法使用记录语法.
但是因为在编译期间简单地将记录转换为元组,所以我们很容易手动构建它们:
-record(some_rec, {a, b}).
make_record(Rec, Values) ->
list_to_tuple([Rec | Values]).
test() ->
R = make_record(some_rec, ["Hej", 5]), % Dynamically create record
#some_rec{a = A, b = B} = R, % Access it using record syntax
io:format("a = ~p, b = ~p~n", [A, B]).
Run Code Online (Sandbox Code Playgroud)
或者,如果您在编译时列出了该函数应该能够构造的所有记录,您还可以使用字段名称:
%% List of record info created with record_info macro during compile time
-define(recs,
[
{some_rec, record_info(fields, some_rec)}
]).
make_record_2(Rec, Fields, Values) ->
ValueDict = lists:zip(Fields, Values),
% Look up the record name and fields in record list
Body = lists:map(
fun(Field) -> proplists:get_value(Field, ValueDict, undefined) end,
proplists:get_value(Rec, ?recs)),
list_to_tuple([Rec | Body]).
test_2() ->
R = make_record_2(some_rec, [b, a], ["B value", "A value"]),
#some_rec{a = A, b = B} = R,
io:format("a = ~p, b = ~p~n", [A, B]).
Run Code Online (Sandbox Code Playgroud)
使用第二个版本,您还可以进行一些验证,以确保使用正确的字段等.
在动态处理记录时要记住的其他有用构造是#some_rec.a表达式,它计算s中a字段的索引,给定元组和索引some_rec的element(N, Tuple)函数返回该索引中的元素.