【问题标题】:Syntax Error while accessing a field in a record访问记录中的字段时出现语法错误
【发布时间】:2010-10-22 22:40:20
【问题描述】:

我遇到了一个很容易解决的问题。在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

我做错了什么?

【问题讨论】:

  • 问题是您试图将运行时问题打包到编译时。这意味着您正在尝试在程序编译期间用其实际值 [在程序执行期间可用] 评估和替换 Field 。通常,问题是通过预处理或元编程来解决的。不幸的是,我不知道 Erlang 的最佳方法是什么。

标签: erlang record


【解决方案1】:

如果您只想枚举记录值,您可以使用element/2 并枚举从 2 (the first element is a record name) 到 tuple_size(记录) 的元素。

如果您想在运行时按名称访问记录字段,您可以在编译时创建辅助 proplist,如下所示:

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.

【讨论】:

  • 我接受了这个,因为它解决了问题中提到的问题,但事实证明我的代码可以重组为根本不需要这样做(我最终删掉了我的一半代码)。万岁!
【解决方案2】:

记录在编译时转换为数组,这意味着所有字段访问也转换为 erlang:element 调用。因此,变量不能用作字段名称,必须在编译时知道 - 正如 Damg 已经回答的那样。

我知道的“解决方法”是使用 proplists、dicts 等代替记录,或者使用 Ulf Wiger 的 exprecs 来生成记录访问函数。

【讨论】:

    【解决方案3】:

    另一种方法是将记录转换为 proplist 并使用 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).
    

    将产生以下proplist:

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

    然后例如获取字段value2的值:

    > proplists:get_value(value2, Proplist).
    2
    

    【讨论】:

      猜你喜欢
      • 2019-11-19
      • 2017-10-08
      • 1970-01-01
      • 2012-05-11
      • 2019-11-16
      • 1970-01-01
      • 1970-01-01
      • 2019-05-24
      • 1970-01-01
      相关资源
      最近更新 更多