Boolean expression pattern matching with tuples

I have a case clause (contrived for the purpose of this question):

level = 4
has_children_or_no_children = :no_children

case {level, has_children_or_no_children} do
  {3, :has_children} ->
    1

  {4, :no_children} ->
    2

  _ ->
    false
end

This works well. Normally though, with a single value in the case clause I can use a guard to match on greater than / less than integer values:

level = 4
has_children_or_no_children = :no_children

case level do
  n when n < 5 ->
    1

  n when n > 0 ->
    2

  _ ->
    false
end

Which again works well, but I can’t use these guard clauses inside the tuple passed to case in the first example:

level = 4
has_children_or_no_children = :no_children

# DOES NOT WORK
case {level, has_children_or_no_children} do
  {n when n < 5, :has_children} ->
    1

  {n when n > 0, :no_children} ->
    2

  _ ->
    false
end

Is there a way to perform a boolean test and a comparison with an atom simultaneously, to avoid having to nest case statements and duplicate the code to be executed?

The guard needs to be outside of the match:

case {level, has_children_or_no_children} do
  {n, :has_children} when n < 5 -> 1
  {n, :no_children} when n > 0 -> 2
  _ -> false
end
3 Likes

You need to move the when outside the tuple and then it works

level = 4
has_children_or_no_children = :no_children

case {level, has_children_or_no_children} do
  {n, :has_children} when n < 5 ->
    1

  {n, :no_children} when n > 0 ->
    2

  _ ->
    false
end
2 Likes

Ahh that seems so easy (and nice) now that I see the solution! Thanks for your help :slight_smile:

1 Like