Pattern matching is one of Elixir's most powerful and beloved features. If you’re coming from another language, you may have used pattern matching with lists or maps, but Elixir takes it a step further. In Elixir, you can even pattern-match strings, making it easy to write expressive, concise code for string manipulation. Let’s dive into an example to see how this works in practice.

The code

Here's a small function that uses pattern matching on strings to differentiate between YouTube video and playlist IDs.

def course_type(youtube_course_id) do
  case youtube_course_id do
    "PL" <> _rest -> :playlist
    _ -> :video
  end
end

The course_type/1 function takes a youtube_course_id and determines if it represents a playlist or a video.

  • If the youtube_course_id starts with "PL", it’s treated as a playlist, and the function returns :playlist.
  • If the ID doesn’t start with "PL", it’s considered a video, and the function returns :video.

How it works

Let's break down how pattern matching is applied to the string.

  1. Pattern Matching with <> (Concatenation Operator)

    In Elixir, the <> operator is used for string concatenation. However, in pattern matching, it also allows us to split a string into parts.

    The line "PL" <> _rest -> :playlist checks if youtube_course_id begins with the substring "PL". If it does, the rest of the string is bound to the variable _rest. Here, _rest is an unused variable, indicated by the underscore _. By convention, variables prefixed with an underscore in Elixir are placeholders, signaling that we don’t care about their value.

  2. The Default Case

    The underscore _ -> :video acts as a catch-all pattern. If youtube_course_id doesn’t start with "PL", it matches this pattern, and the function returns :video.

When to use this pattern

This pattern is particularly useful when you need to categorize strings based on prefixes, like detecting types of identifiers, recognizing commands, or handling formats with specific string prefixes. Pattern matching on strings allows you to avoid cumbersome conditional logic and express your intent more clearly.

Example usage

Here’s how you might use this function in a simple Elixir script:

IO.inspect(course_type("PL1234567890")) # Output: :playlist
IO.inspect(course_type("VID1234567890")) # Output: :video

In the first example, "PL1234567890" matches the pattern "PL" <> _rest, so it returns :playlist. In the second example, "VID1234567890" doesn’t match "PL", so it defaults to :video.

Why this approach is powerful

Using pattern matching for string handling in Elixir offers several advantages:

  • Clarity: The code communicates its intent without conditional statements.
  • Conciseness: There’s no need for nested if or case statements, making the function shorter and easier to read.
  • Immutability: Pattern matching works seamlessly with Elixir’s immutable data structures, providing a functional approach to conditional logic.

Final thoughts

Pattern matching on strings in Elixir is a feature that often surprises newcomers and delights experienced developers. It allows for elegant and readable code when working with string patterns, as demonstrated by the course_type/1 function. This approach is great for tasks like categorizing strings by prefix, checking formats, and more.

With just a few lines of code, you can perform powerful string manipulations and classifications. Embracing this feature of Elixir can make your code cleaner, easier to maintain, and more idiomatic.

original source