Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Updating deeply nested struct

Tags:

elixir

So let's say I have the following structure:

%Car{details: [%CarDetail{prices: [%Price{euro: 5}]}]}

and I want to add another price struct to the prices list of the car detail, how would I do that?

Obviously the real example is way deeper so I cannot use pattern matching and I can't come up with a way to use put_in/3 or something of the kind.

Some help would be appreciated. Thank you.

like image 264
NoDisplayName Avatar asked Sep 20 '16 11:09

NoDisplayName


2 Answers

You can use Kernel.update_in/3 to traverse nested structures. It will not work by simply passing a list of keys to update_in, because neither structs nor lists implement the access protocol. This is where Access.key!/1 and Access.all come in. Be aware though, that the following piece of code will add the price to all car details, should there be more than one. If you need to update specific details only, you can either use Access.at/1 or implement your own access function.

update_in car, [Access.key!(:details), Access.all, Access.key!(:prices)], fn(prices) ->
  [%Price{euro: 12345} | prices]
end
like image 90
Patrick Oscity Avatar answered Sep 28 '22 15:09

Patrick Oscity


The macro put_in/2 makes this easy:

def add_price(%Car{details: %CarDetails{prices: prices}} = car, new_price) do
  put_in(car.details.prices, [%Price{euro: new_price} | prices])
end
like image 29
valo Avatar answered Sep 28 '22 16:09

valo