Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Elixir: Capturing the rest of a map using pattern matching

Tags:

I want to simultaneously match on a specific key in a map, and capture the rest of that map. I was hoping something like this would work:

iex(10)> %{"nodeType" => type | rest} = %{"nodeType" => "conditional", "foo" => "bar"}

** (CompileError) iex:10: cannot invoke remote function IEx.Helpers.|/2 inside match

The goal is to write a set of functions which take a map, pattern match on one of the map's fields, and perform some transformations on the rest of the map.

def handle_condition(%{"nodeType" => "condition" | rest}) do
  # do something with rest
done
def handle_expression(%{"nodeType" => "expression" | rest}) do
  # do something with rest
done

But it looks like I'll need the callee to pass the nodeType separately unless I'm missing something.

like image 961
D. Vroom Duke Avatar asked May 15 '15 16:05

D. Vroom Duke


People also ask

What is Elixir pattern matching?

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 lot pattern matching?

Pattern matching is the act of checking one or more inputs against a pre-defined pattern and seeing if they match. In Elm, there's only a fixed set of patterns we can match against, so pattern matching has limited application.

What is a map Elixir?

12.3) Maps are the "go to" key-value data structure in Elixir. Maps can be created with the %{} syntax, and key-value pairs can be expressed as key => value : iex> %{} %{} iex> %{"one" => :two, 3 => "four"} %{3 => "four", "one" => :two}


2 Answers

You can easily capture the whole map - maybe this will be enough?

def handle_condition(all = %{"nodeType" => "condition"}) do
  # do something with all
end

Or:

def handle_condition(all = %{"nodeType" => "condition"}) do
  all = Map.delete(all, "nodeType")
  # do something with all
end
like image 141
Paweł Obrok Avatar answered Oct 14 '22 10:10

Paweł Obrok


Another nice way of achieving this is by using Map.pop/2:

def handle(%{} = map), do: handle(Map.pop(map, "nodeType"))

def handle({"condition", rest}) do
  # ... handle conditions here
end

def handle({"expression", rest}) do
  # ... handle expressions here
end
like image 35
potibas Avatar answered Oct 14 '22 08:10

potibas