I'm having a problem that should be stupidly easy to fix. Following this, I'm trying to access a field in a record. Here's a simplified example that exhibits my problem:
-module(test).
-export([test/0]).
-record(rec, {f1=[], f2=[], f3=[]}).
test() ->
Rec = #rec{f1=[1,2,3], f3=[4,5,6]},
Fields = record_info(fields, rec),
loop(Fields, Rec).
loop([Field|Fields], Rec) ->
[Rec#rec.Field|loop(Fields, Rec)]; %% <-- This is line 12.
loop([], _Rec) ->
[].
When I try to compile test, I get a syntax error:
./test.erl:12: syntax error before: Field
What am I doing wrong?
If you only want to enumerate record values you can use element/2 and enumerate elements from 2 (the first element is a record name) to tuple_size(Record).
If you want to access record fields by name at run time you can create auxiliary proplist at compile time like this:
Fields = lists:zip(record_info(fields, rec),
lists:seq(2, record_info(size, rec)))
Note that record_info() always evaluated at compile time.
And then query field value with function similar to this:
get_record_value(Name, Record, Fields) ->
case proplists:get_value(Name, Fields) of
undefined ->
undefined;
N when is_integer(N) ->
element(N, Record)
end.
Records are converted into arrays in compile-time, meaning that all field accesses are converted to erlang:element calls as well. Thus variables cannot be used as field names must be known at compile-time - as Damg already answered.
The "workarounds" I am aware of are either using proplists, dicts, etc. instead of records, or use Ulf Wiger's exprecs to generate record access functions.
Another way is converting the record into a proplist and using the proplists
library module to iterate or access specific fields. This example:
-module(test).
-export([start/0]).
-record(test, {value1, value2, value3}).
start() ->
R = #test{value1=1, value2=2, value3=3},
Fields = record_info(fields, test),
Values = tl(tuple_to_list(R)),
lists:zip(Fields, Values).
Will produce the following proplist:
> c("test").
> Proplist = test:start().
[{value1,1},{value2,2},{value3,3}]
Then for example to get value of field value2
:
> proplists:get_value(value2, Proplist).
2