Consider a (smelly, non-idiomatic) function like the below:
def update_2d(array, inds, val) do
[first_coord, second_coord] = inds
new_arr = List.update_at(array, second_coord, fn(y) ->
List.update_at(Enum.at(array, second_coord),
first_coord, fn(x) -> val end) end)
end
This function will take in a list of lists, a list of two indices, and a value to insert within the list of lists at the location specified by the indices.
As a first step to making this more Elixir-ey, I start laying pipe:
array
|> Enum.at(second_coord)
|> List.update_at(first_coord, fn(x) -> val end)
That gets me most of the way there, but how do I pipe that output into the anonymous function of the last List.update_at
call? I can nest it within the original call, but that seems like giving up:
List.update_at(array, second_coord, fn(y) ->
array
|> Enum.at(second_coord)
|> List.update_at(first_coord, fn(x) -> val end)
end)
You can simply bind to a variable to capture your first result and then replace it in the second List.update_at/3
call
def update_2d(array, inds = [first_coord, second_coord], val) do
updated =
array
|> Enum.at(second_coord)
|> List.update_at(first_coord, fn(x) -> val end)
List.update_at(array, second_coord, fn(x) -> updated end)
end
You can also use the capture operator to do this:
def update_2d(array, inds = [first_coord, second_coord], val), do:
array
|> Enum.at(second_coord)
|> List.update_at(first_coord, fn(x) -> val end)
|> (&(List.update_at(array, second_coord, fn(y) -> &1 end))).()
I find using a variable much more readable, but the option is there.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With