Expat v1.0.2 Expat

Pattern Matching as Macros

use Expat

This will import defpat and expat into scope.

Link to this section Summary

Functions

Define a new named pattern

Same as defpat but defines private patterns

Expand an expression using named patterns

Link to this section Types

Link to this type guarded_pattern()
guarded_pattern() :: {:when, list(), [simple_call(), ...]}
Link to this type pattern()
pattern() :: simple_call() | guarded_pattern()
Link to this type simple_call()
simple_call() :: {atom(), keyword(), [Macro.t()]}

Link to this section Functions

Link to this macro defpat(pattern) (macro)
defpat(pattern()) :: Macro.t()

Define a new named pattern.

This function takes only the function head as argument. You may also specify a guard, but never a do block.

Variables present in the function head can be later bound. Guards if any are also expanded at call site, for example in def, case, fn expressions. See expat/1 for more.

Examples

defpat person(%Person{name: name})
defpat adult(%{age: age}) when age > 18
Link to this macro defpatp(pattern) (macro)
defpatp(pattern()) :: Macro.t()

Same as defpat but defines private patterns

Link to this macro expat(ast) (macro)
expat(Macro.t()) :: Macro.t()

Expand an expression using named patterns.

expat stands for expand pattern in an expression. It’s also the name of the library :).

Note that for this to work, the macros that define the named patterns should already have been compiled and in scope. For this reason, most of the time, named patterns should be defined on separate modules and imported for use.

Example

You define a module for your named patterns

defmodule MyPatterns do
  use Expat

  @doc "Matches when n is legal age to vote"
  defpat adult_age(n) when n > 18
end

Then you can import it and use it’s macros

defmodule Foo do
   use Expat
   import MyPatterns

   def foo(x) do
     # Tell expat that we want the case
     # clauses being able to use guards
     # from the named pattern.
     #
     # foo(20) => :vote
     #
     expat case x do
       adult_age() -> :vote
     end
   end

   # You can also use expat at the `def`
   # level (or defp, defmacro, etc)
   #
   # In this case, we are asking expat to
   # also expand the named patterns it
   # sees on our function head, and the
   # guards it produces are added to our
   # function definition.
   #
   # vote(20) => {:voted, 20}
   # vote(20) => no function match error
   #
   expat def vote(adult_age(n: x)) do
     {:voted, x}
   end
end

You can even use expat only once at the module level, then all it’s def, case, fn, … will be able to use named patterns.

 use Expat
 import MyPatterns, only: [adult_age: 1]

 expat defmodule Ellections do

    def vote(adult_age(n: x)) do
      {:ok, x}
    end

    def vote(_), do: :error
 end