Вы не можете использовать синтаксис записи, если у вас нет доступа к записи во время компиляции.
Но поскольку записи просто преобразуются в кортежи во время компиляции, нам действительно легко создать их вручную:
-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]).
Или, если во время компиляции составляется список всех записей, которые должна быть в состоянии построить функция, вы также можете использовать имена полей:
%% 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]).
Со второй версией вы также можете выполнить некоторую проверку, чтобы убедиться, что вы используете правильные поля и т. Д.
Другими полезными конструкциями, которые следует учитывать при динамической работе с записями, является выражение #some_rec.a
, которое оценивает индекс поля a
в some_rec
s, и функция element(N, Tuple)
, которая дает кортеж и index возвращает элемент в этом индексе.