NoDisplayName
NoDisplayName

Reputation: 15746

Updating deeply nested struct

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.

Upvotes: 7

Views: 4185

Answers (2)

Patrick Oscity
Patrick Oscity

Reputation: 54724

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

Upvotes: 19

valo
valo

Reputation: 1752

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

Upvotes: 1

Related Questions