Some languages tout themselves as providing pattern matching features. In general, pattern-matching is used in evaluating variables e.g. in Kotlin:

var statusCode : Int val errorMessage = when ( statusCode ) { 401 -> "Unauthorized" 403 -> "Forbidden" 500 -> "Internal Server Error" else -> "Unrecognized Status Code" }

This usage is a switch statement on steroids. However, in general, pattern matching applies much more widely. In the following snippet, one checks first regular HTTP status error codes, and if none is found, defaults to a more generic error message:

val errorMessage = when { statusCode == 401 -> "Unauthorized" statusCode == 403 -> "Forbidden" statusCode - 400 < 100 -> "Client Error" statusCode == 500 -> "Internal Server Error" statusCode - 500 < 100 -> "Server Error" else -> "Unrecognized Status Code" }

Still, it’s limited.

Elixir is a dynamically-typed language running on the Erlang OTP that brings pattern matching to a whole new level. Elixir’s pattern-matching can be used for simple variable destructuring:

{ a , b , c } = { :hello , "world" , 42 }

a will be assigned :hello , b "world" and c 42.

It also can be used for more advanced destructuring, on collections:

[ head | tail ] = [ 1 , 2 , 3 ]

head will be assigned 1, and tail [2, 3] .

Yet, it goes even beyong that, for function overloading. Being a functional language, Elixir doesn’t have keywords for loops ( for or while ): loops need to be implemented using recursion.

As an example, let’s use recursion to compute the size of a List . In Java, it’s easy because there’s a size() method, but Elixir API doesn’t provide such a feature. Let’s implement it in pseudo-code, the Elixir way - using recursion.

public int lengthOf ( List <?> item ) { return lengthOf ( 0 , items ); } private int lengthOf ( int size , List <?> items ) { if ( items . isEmpty ()) { return size ; } else { return lengthOf ( size + 1 , items . remove ( 0 )); } }

This can be translated into Elixir nearly line by line:

def length_of ( list ), do : length_of ( 0 , list ) defp length_of ( size , list ) do if [] == list do size else [ _ | tail ] = list (1) length_of ( size + 1 , tail ) end end

1 Pattern matching with variable destructuring. The head value is assigned to the _ variable, which means there’s no way to reference it later - because it’s not useful.

However, as mentioned previously, Elixir pattern matching also applies to function overloading. Hence, the nominal way to write Elixir would be:

def list_len ( list ), do : list_len ( 0 , list ) defp list_len ( size , []), do : size (1) defp list_len ( size , list ) do (2) [ _ | tail ] = list list_len ( size + 1 , tail ) end

1 Call this function if the list is empty 2 Call this function otherwise