2010-10-22 33 views
1

我遇到了应该很容易修复的问题。在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 

我在做什么错?

+1

的问题是,您要收拾运行在编译时关心。这意味着您正在尝试在程序编译期间评估和替换Field的真实值[在程序执行期间可用]。通常,问题可以通过预处理或元编程来解决。不幸的是,我不知道Erlang的最佳方法是什么。 – Damg 2010-10-22 22:49:50

回答

2

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

如果你想通过名称在运行时访问记录字段,你可以这样建立在编译时辅助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. 
+0

我接受这个问题,因为它解决了问题中提到的问题,但事实证明,我的代码可能会被重新构造为根本不需要这样做(我最终裁剪了大约一半的代码)。万岁! – nmichaels 2010-10-23 17:16:14

1

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

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

0

另一种方式是在记录转换成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 
相关问题