2009-02-27 11 views
3

Yani rekor tanımların oldukça derin hiyerarşiyi var:Erlang'da bir sububsub kayıt alanındaki bir değeri değiştirmek için daha kolay bir yol var mı?

-record(cat,   {name = '_',   attitude = '_',}). 
-record(mat,   {color = '_',   fabric = '_'}). 
-record(packet,   {cat = '_',   mat = '_'}). 
-record(stamped_packet, {packet = '_',   timestamp = '_'}). 
-record(enchilada, {stamped_packet = '_', snarky_comment = ""}). 

Ve şimdi bir enchilada var ve ben birinin değeri hariç bunun gibi var yenisini yapmak istiyorum subsubsubrecords. İşte yaptığım şey. Bu konuda düşünerek

update_attitude(Ench0, NewState) 
    when is_record(Ench0, enchilada)-> 

    %% Pick the old one apart. 
    #enchilada{stamped_packet  = SP0} = Ench0, 
    #stamped_packet{packet = PK0} = SP0, 
    #packet{cat = Tag0} = PK0, 

    %% Build up the new one. 
    Tude1 = Tude0#cat{attitude = NewState}, 
    PK1 = PK0#packet{cat = Tude1}, 
    SP1 = SP0#stamped_packet{packet = PK1}, 

    %% Thank God that's over. 
    Ench0#enchilada{stamped_packet = SP1}. 

Sadece acı verici. Daha iyi bir yolu var mı? yapıları Erlang en güçlü parçası değildir, zaten

update_attitude(E = #enchilada{ 
    stamped_packet = (SP = #stamped_packet{ 
     packet = (P = #packet{ 
     cat = C 
    })})}, NewState) -> 
    E#enchilada{ 
     stamped_packet = SP#stamped_packet{ 
     packet = P#packet{ 
      cat = C#cat{ 
      attitude = NewState 
    }}}}. 

:

cevap

4

, geçici değişkenleri elide ve yapabilirsiniz:

update_attitude(E = #enchilada{stamped_packet = (P = #packet{cat=C})}, 
       NewAttitude) -> 
    E#enchilada{stamped_packet = P#packet{cat = C#cat{attitude=NewAttitude}}}. 

Yariv Sadan aynı konu yüzünden hayal kırıklığına uğrayan ve yazmayı sağlayacak Recless, a type inferring parse transform for records yazdım:

-compile({parse_transform, recless}). 

update_attitude(Enchilada = #enchilada{}, Attitude) -> 
    Enchilada.stamped_packet.packet.cat.attitude = Attitude. 
1

bu deneyin. Hynek anlaşılacağı gibi