2010-10-22 50 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 
相關問題