Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pattern match a list of any size in Elixir

Tags:

elixir

I'm new to Elixir. I want to define a function that accepts only lists, but that can be of any size.

I could define a function that accepts an empty list like this:

def doit(my_list = []) do
  IO.puts my_list
end

or just one item, like this:

def doit([first]) do
  IO.puts my_list
end

but how do I allow any size list? I know I can accept anything like this:

def doit(my_list) do
  IO.puts my_list
end

but wouldn't it be more correct to enforce that it is a list using pattern matching?

like image 536
you786 Avatar asked Jul 13 '17 18:07

you786


People also ask

What is pattern matching in Elixir?

Pattern matching allows developers to easily destructure data types such as tuples and lists. As we will see in the following chapters, it is one of the foundations of recursion in Elixir and applies to other types as well, like maps and binaries.

What is pin operator in Elixir?

it matches the value on the left hand side with the value on the right hand side. if it matches and if the left hand side includes a variable, it assigns the corresponding value from the right hand side to the variable.

What is pattern matching in ML?

A special feature of languages in the ML family is pattern matching. It allows simple access to the components of complex data structures. A function definition most often corresponds to pattern matching over one of its parameters, allowing the function to be defined by cases.

What is pattern matching Haskell?

Overview. We use pattern matching in Haskell to simplify our codes by identifying specific types of expression. We can also use if-else as an alternative to pattern matching. Pattern matching can also be seen as a kind of dynamic polymorphism where, based on the parameter list, different methods can be executed.


3 Answers

You can do it as below with pure pattern match and without the guards:

def any_list(list = [head | tail = []]) do IO.puts("Single Element") end

def any_list(list = [head | tail ]) do IO.puts("Any list") end

def any_list([]) do IO.puts("Empty list") end

like image 103
reggae Avatar answered Sep 29 '22 04:09

reggae


As an alternative to pattern matching, you can use the is_list/1 guard function, which does a type check on the function argument:

def doit(my_list) when is_list(my_list) do
  # code goes here
end

Or even use it with the size check, if necessary:

def doit(my_list) when is_list(my_list) and length(my_list) > 0 do
  # code goes here
end
like image 37
Máté Avatar answered Sep 29 '22 04:09

Máté


As far as I know there's no single pattern to match any list. [] will match an empty list and [_ | _] will match any non-empty list, but there's no way to combine them using a pattern.

You can do this with function guards though, using is_list/1:

def doit(my_list) when is_list(my_list) do
  # my_list is guaranteed to be a list
end
like image 21
Dogbert Avatar answered Sep 29 '22 04:09

Dogbert