I think one thing is missing from this discussion and that‘s the notion of violating DRY by having ways to calculate the computed value from various sources of data. Instead of trying to avoid repetition by limiting the number of inputs (only struct or only changeset) you can also keep both inputs, but delegate the business logic in question to a shared helper.
def with_computed(%Ecto.Changeset{} = cs) do
a = get_field(cs, :a)
b = get_field(cs, :b)
put_change(cs, :x, compute_x(a, b))
end
def with_computed(%Struct{} = struct) do
%{struct | x: compute_x(struct.a, struct.b)}
end
defp compute_x(a, b), do: a + b






















