Синтаксическая ошибка при доступе к полю в записи - PullRequest
1 голос
/ 23 октября 2010

У меня проблема, которую глупо легко исправить. После this я пытаюсь получить доступ к полю в записи. Вот упрощенный пример, который демонстрирует мою проблему:

-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) ->
    [].

Когда я пытаюсь скомпилировать тест, я получаю синтаксическую ошибку:

./test.erl:12: syntax error before: Field

Что я делаю не так?

Ответы [ 3 ]

2 голосов
/ 23 октября 2010

Если вы хотите только перечислить значения записей, вы можете использовать element / 2 и перечислять элементы от 2 ( первый элемент - это имя записи ) до tuple_size (Запись).

Если вы хотите получить доступ к полям записи по имени во время выполнения, вы можете создать вспомогательный список поддержки во время компиляции следующим образом:

Fields = lists:zip(record_info(fields, rec),
                   lists:seq(2, record_info(size, rec)))

Обратите внимание, что record_info () всегда вычисляется во время компиляции.

А затем запрашивает значение поля с функцией, подобной этой:

get_record_value(Name, Record, Fields) ->
    case proplists:get_value(Name, Fields) of
        undefined ->
            undefined;
        N when is_integer(N) ->
            element(N, Record)
    end.
1 голос
/ 23 октября 2010

Записи преобразуются в массивы во время компиляции, а это означает, что все обращения к полям также преобразуются в вызовы erlang: element. Таким образом, переменные нельзя использовать, так как имена полей должны быть известны во время компиляции - как уже ответил Дамг.

«Обходные пути», о которых я знаю, либо используют проплисты, дикты и т. Д. Вместо записей, либо используют exprecs Ульфа Вигера для генерации функций доступа к записям.

0 голосов
/ 18 апреля 2013

Другой способ - преобразовать запись в проплист и использовать библиотечный модуль proplists для итерации или доступа к определенным полям.Этот пример:

-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).

создаст следующий проплист:

> c("test").
> Proplist = test:start().
[{value1,1},{value2,2},{value3,3}]

Затем, например, получить значение поля value2:

> proplists:get_value(value2, Proplist).
2
...