This happens as the code recursively works through each element of the list. Consider this:
defmodule Fp do
def shunt([], ys),
do: ys
def shunt([x|xs], ys),
do: shunt(xs, [x|ys])
def reverse(xs),
do: shunt(xs,[])
def foldl([], acc, _fun),
do: acc
def foldl([x|xs], acc, fun),
do: foldl(xs, fun.(x,acc), fun) # this recursive call works through the list
def map(xs, fun) do
xs
|> foldl([], cons_result_fn(fun))
|> reverse()
end
defp cons_result_fn(fun),
do: fn (x, acc) -> [fun.(x)|acc] end
# do: &([fun.(&1)|&2])
end
defmodule Demo do
import Fp, [only: [map: 2, foldl: 3]]
def lookup_meal_product(meal_id) do
case meal_id do
1 ->
{:ok, 450}
2 ->
{:ok, 330}
_ ->
{:error, "Not found"}
end
end
defp merge_meal_product(%{meal_id: id} = org) do
with {:ok, product_id} <- lookup_meal_product(id) do
Map.put(org, :product_id, product_id)
else
_ -> # no product id
org
end
end
def product_map(meals),
do: map(meals, &merge_meal_product/1)
defp put_meal_product(%{meal_id: id} = org, acc) do
with {:ok, product_id} <- lookup_meal_product(id) do
[Map.put(org, :product_id, product_id) | acc]
else
_ -> # no product id - skip this meal
acc
end
end
def product_foldl(meals),
do: foldl(meals, [], &put_meal_product/2)
end
meals = [%{meal_id: 1}, %{meal_id: 2}, %{meal_id: 9}]
meal_products = Demo.product_map(meals)
IO.inspect(meal_products)
meal_products = Demo.product_foldl(meals)
IO.inspect(meal_products)
$ elixir demo.exs
[%{meal_id: 1, product_id: 450}, %{meal_id: 2, product_id: 330}, %{meal_id: 9}]
[%{meal_id: 2, product_id: 330}, %{meal_id: 1, product_id: 450}]
$