In Elixir, control flow is often managed using pattern matching in various constructs such as if
, case
, with
, and cond
. Here is an explanation of how each of these control flow structures works with pattern matching:
if
Statements:If statements in Elixir are used to make decisions based on the truthiness of a condition but are not as commonly used as in other programming languages.
Pattern matching can be used within
if
statements to match specific values or patterns.Elixir does not provide a
else if
syntax.Example:
if x == 1 do IO.puts("Value is 1") else IO.puts("Value is not 1") end
case
Expressions:Case statements serve as the foundational and commonly used control flow structure in Elixir. They are utilized to compare a single term against multiple potential patterns, with the body of the first matching clause being executed and returned.
Case expressions in Elixir allow for pattern matching against multiple clauses.
Each clause can contain a pattern and corresponding code to execute if the pattern matches.
Example:
defmodule TypeCheck do def check_type(value) do case value do x when is_integer(x) -> IO.puts("Integer: #{x}") x when is_float(x) -> IO.puts("Float: #{x}") x when is_binary(x) -> IO.puts("Binary: #{x}") x when is_list(x) -> IO.puts("List: #{inspect(x)}") _ -> IO.puts("Unknown type") end end end TypeCheck.check_type(123) # Output: Integer: 123 TypeCheck.check_type(3.14) # Output: Float: 3.14 TypeCheck.check_type("elixir") # Output: Binary: elixir TypeCheck.check_type([1, 2, 3]) # Output: List: [1, 2, 3] TypeCheck.check_type(:atom) # Output: Unknown type
with
Construct:Elixir's
with
statements are designed to capture the successful outcomes of a series of operations while providing a built-in mechanism to handle any errors that may occur.They are particularly useful when you need to execute multiple operations, especially those that are prone to failure, and all operations must succeed for the overall result to be returned.
Examples:
with {:ok, result} <- {:ok, "success"}, {:ok, new_result} <- {:ok, result <> "!"} do IO.puts("Final result: #{new_result}") else _ -> IO.puts("Pattern match failed") end
cond
Clauses:cond
clauses in Elixir are used for multiple conditional checks with pattern matching.Each clause contains a condition followed by a pattern match and corresponding code.
If none of the clauses are evaluated as true, a
CondClauseError
will be raised. To ensure a match in such cases, includetrue ->
as the final clause as a fallback option.Example:
x = 3 result = cond do x == 1 -> "Value is equal to 1" x == 2 -> "Value is equal to 2" x > 2 && x < 5 -> "Value is greater than 2 but less than 5" true -> "Value is neither 1 nor 2" end IO.puts(result) # Output: Value is greater than 2 but less than 5
What makes cond
so powerful that you can execute functions in the clauses - something
that you cannot do with pattern matching.
Example:
str = "The quick brown fox"
result = cond do
String.contains?(str, "dog") -> "Contains 'dog'"
String.contains?(str, "fox") -> "Contains 'fox'"
String.length(str) > 10 -> "String length is greater than 10"
true -> "None of the specific conditions met"
end
IO.puts(result) # Output: "Contains 'fox'"
In Elixir, pattern matching is deeply integrated into control flow constructs, allowing for expressive and concise code that leverages the power of pattern matching to make decisions and handle different scenarios effectively.