Correct way to write conditional statements

Hello,

I’m very new to Elixir (and FP in general) and currently trying to wrap my head around the elixir way of writing conditonal statements. Right now I’m stuck. I’m implementing a custom Ecto.changeset validator. In (non FP/Elixir) pseudo code I want something like this:

if (spared_until != nil and spared_share == 0:
   throw error
else if (spared_until == nil and sphared_share != 0:
   throw error
else:
   return changeset

But I’m not sure which way would be the best, pattern matching, cond, with, if etc. There seems to be so much possibilities but I can’t figure out a way to make any possibilty work.

If you want to decide on whether something is true or false, use if, if you have many conditions that would result in nested if else if, use cond, if you need to pattern match and want to branch on different patterns, use case.

Also, in ecto you do not raise/throw on invalid values, you add an error to the changeset and return the altered changeset.

1 Like

Thank you for your fast reply! I ended up writing something like this:

  defp validate_spared_share(changeset) do
    spared_until = get_field(changeset, :spared_until)
    spared_share = get_field(changeset, :spared_share)

    cond do
      spared_until != nil and spared_share == 0 ->
        add_error(changeset, :spared_share, "must be greater than 0 if spared_until is set")
      spared_until == nil and spared_share != 0 ->
        add_error(changeset, :spared_share, "must be 0 if spared_until is not set")
      true ->
        changeset
    end
  end
``

The first condition can be put on pattern matching functions header. For example…

defp validate_spared_share(changeset) do
  do_validate_spared_share(changeset, get_field(changeset, :spared_until), get_field(changeset, :spared_share))
end

defp do_validate_spared_share(changeset, nil, spared_share) when spared_share != 0 do
  ...
end

defp do_validate_spared_share(changeset, spared_until, 0) when not is_nil(spared_until) do
  ...
end

defp do_validate_spared_share(changeset, _, _) do
  ...
end

Ah, I saw this pattern somewhere too already! Which ‘version’ would be considered best practice in Elixir?

The one that is easier for you to understand in 1 month :slight_smile:

1 Like