Cóż, nie możesz użyć składni rekordu, jeśli nie masz dostępu do rekordu podczas kompilacji.
Ale ponieważ rekordy są po prostu przekształcona krotki podczas kompilacji to nam bardzo łatwo skonstruować je ręcznie:
-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]).
Lub, jeśli w czasie kompilacji zrobić listę wszystkich rekordów, że funkcja powinna być w stanie budowy, można użyć nazwy pól także:
%% 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]).
z drugiej wersji można też zrobić jakąś weryfikację, aby upewnić się, że używasz odpowiedniego pola itd
Inne użyteczne konstrukcje, o których należy pamiętać podczas dynamicznej pracy z rekordami, to wyrażenie #some_rec.a
, które ocenia indeks pola a
s, a funkcja element(N, Tuple)
, która dała krotce i indeksowi zwracać element w tym indeksie.
Są one konwertowane na krotki, a nie na tablice. – ZeissS
Dzięki za poprawkę. – Zed
dziękuję, nauczyłem się czegoś nowego dzisiaj – nagaru