Is there an easier way to modify a value in a subsubsub record field in Erlang?
Question
So I've got a fairly deep hierarchy of record definitions:
-record(cat, {name = '_', attitude = '_',}).
-record(mat, {color = '_', fabric = '_'}).
-record(packet, {cat = '_', mat = '_'}).
-record(stamped_packet, {packet = '_', timestamp = '_'}).
-record(enchilada, {stamped_packet = '_', snarky_comment = ""}).
And now I've got an enchilada, and I want to make a new one that's just like it except for the value of one of the subsubsubrecords. Here's what I've been doing.
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}.
Just thinking about this is painful. Is there a better way?
Solution
As Hynek suggests, you can elide the temporary variables and do:
update_attitude(E = #enchilada{stamped_packet = (P = #packet{cat=C})},
NewAttitude) ->
E#enchilada{stamped_packet = P#packet{cat = C#cat{attitude=NewAttitude}}}.
Yariv Sadan got frustrated with the same issue and wrote Recless, a type inferring parse transform for records which would allow you to write:
-compile({parse_transform, recless}).
update_attitude(Enchilada = #enchilada{}, Attitude) ->
Enchilada.stamped_packet.packet.cat.attitude = Attitude.
OTHER TIPS
Try this:
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
}}}}.
anyway, structures is not most powerful part of Erlang.
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow