\section{Pattern Matching}
\label{Sec::PatternMatching}

Actor programming implies a message passing paradigm.
This means that defining message handlers is a recurring task.
The easiest and most natural way to specify such message handlers is pattern matching.
Unfortunately, C++ does not provide any pattern matching facilities.
%A general pattern matching solution for arbitrary data structures would require a language extension.
Hence, we provide an internal domain-specific language to match incoming messages.

\subsection{Basics}
\label{Sec::PatternMatching::Basics}

Actors can store a set of message callbacks using either \lstinline^behavior^ or \lstinline^message_handler^.
The difference between the two is that the former stores an optional timeout.
The most basic way to define a pattern is to store a set of lambda expressions using one of the two container types.

\begin{lstlisting}
behavior bhvr1{
  [](int i) { /*...*/ },
  [](int i, float f) { /*...*/ },
  [](int a, int b, int c) { /*...*/ }
};
\end{lstlisting}

In our first example, \lstinline^bhvr1^ models a pattern accepting messages that consist of either exactly one \lstinline^int^, or one \lstinline^int^ followed by a \lstinline^float^, or three \lstinline^int^s.
Any other message is not matched and will remain in the mailbox until it is consumed eventually.
This caching mechanism allows actors to ignore messages until a state change replaces its message handler.
However, this can lead to a memory leak if an actor receives messages it handles in no state.
To allow actors to specify a default message handlers for otherwise unmatched messages, \lib provides \lstinline^others^.

\begin{lstlisting}
behavior bhvr2{
  [](int i) { /*...*/ },
  [](int i, float f) { /*...*/ },
  [](int a, int b, int c) { /*...*/ },
  others >> [] { /*...*/ }
};
\end{lstlisting}

Please note the change in syntax for the default case.
The lambda expression passed to the constructor of \lstinline^behavior^ is prefixed by a ''match expression'' and the operator \lstinline^>>^.

\subsection{Atoms}
\label{Sec::PatternMatching::Atoms}

Assume an actor provides a mathematical service for integers.
It takes two arguments, performs a predefined operation and returns the result.
It cannot determine an operation, such as multiply or add, by receiving two operands.
Thus, the operation must be encoded into the message.
The Erlang programming language introduced an approach to use non-numerical
constants, so-called \textit{atoms}, which have an unambiguous, special-purpose type and do not have the runtime overhead of string constants.
Atoms are mapped to integer values at compile time in \lib.
This mapping is guaranteed to be collision-free and invertible, but limits atom literals to ten characters and prohibits special characters.
Legal characters are ``\lstinline[language=C++]^_0-9A-Za-z^'' and the whitespace character.
Atoms are created using the \lstinline^constexpr^ function \lstinline^atom^, as the following example illustrates.

\begin{lstlisting}
atom_value a1 = atom("add");
atom_value a2 = atom("multiply");
// ...
\end{lstlisting}

\textbf{Warning}: The compiler cannot enforce the restrictions at compile time, except for a length check.
The assertion \lstinline^atom("!?") != atom("?!")^ is not true, because each invalid character is mapped to the whitespace character.

An \lstinline^atom_value^ alone does not help us statically annotate function handlers.
To accomplish this, \lib offers compile-time \emph{atom constants}.

\begin{lstlisting}
using add_atom = atom_constant<atom("add")>;
using multiply_atom = atom_constant<atom("multiply")>;
\end{lstlisting}

Using the constants, we can now define message passing interfaces in a convenient way.
\begin{lstlisting}
behavior do_math{
  [](add_atom, int a, int b) {
    return a + b;
  },
  [](multiply_atom, int a, int b) {
    return a * b;
  }
};
\end{lstlisting}

Atom constants define a static member \lstinline^value^ that can be used on the caller side (see Section \ref{Sec::Send}), e.g., \lstinline^send(math_actor, add_atom::value, 1, 2)^.
Please note that the static \lstinline^value^ member does \emph{not} have the type \lstinline^atom_value^, unlike \lstinline^std::integral_constant^ for example.

\clearpage
\subsection{Advanced Match Cases}

Match cases are an advanced feature of \lib and allow you to match on values and to transform data while matching.
A match case begins with a call to the function \lstinline^on^, which returns an intermediate object providing \lstinline^operator>>^.
The right-hand side of the operator denotes a callback, usually a lambda expression, that should be invoked if a tuple matches the types given to \lstinline^on^,

When using the basic syntax, \lib generates the match case automatically.
A verbose version of the \lstinline^bhvr1^ from \ref{Sec::PatternMatching::Basics} is shown below.

\begin{lstlisting}
behavior verbose_bhvr1{
  on<int>() >> [](int i) { /*...*/ },
  on<int, float>() >> [](int i, float f) { /*...*/ },
  on<int, int, int>() >> [](int a, int b, int c) { /*...*/ }
};
\end{lstlisting}

It is worth mentioning that passing the lambdas directly is more efficient, since it allows \lib to select a special-purpose implementation.
The function \lstinline^on^ can be used in two ways.
Either with template parameters only or with function parameters only.
The latter version deduces all types from its arguments and matches for both type and value.
To match for any value of a given type, the template \lstinline^val<T>^ can be used, as shown in the following example.

\begin{lstlisting}
behavior bhvr3{
  on(42) >> [](int i) { assert(i == 42); },
  on("hello world") >> [] { /* ... */ },
  on("print", val<std::string>) >> [](const std::string& what) {
  // ...
  }
};
\end{lstlisting}

\textbf{Note:} The given callback can have less arguments than the pattern.
But it is only allowed to skip arguments from left to right.

\begin{lstlisting}
on<int, float, double>() >> [](double) { /*...*/ }             // ok
on<int, float, double>() >> [](float, double) { /*...*/ }      // ok
on<int, float, double>() >> [](int, float, double) { /*...*/ } // ok

on<int, float, double>() >> [](int i) { /*...*/ } // compiler error
\end{lstlisting}

To avoid redundancy when working with match expressions, \lstinline^arg_match^ can be used as last argument to the function \lstinline^on^.
This causes the compiler to deduce all further types from the signature of any given callback.

\begin{lstlisting}
on<int, int>() >> [](int a, int b) { /*...*/ }
// is equal to:
on(arg_match) >> [](int a, int b) { /*...*/ }
\end{lstlisting}

Note that \lstinline^arg_match^ must be passed as last parameter.
If all types should be deduced from the callback signature, \lstinline^on_arg_match^ can be used, which is a faster alternative for \lstinline^on(arg_match)^.
However, \lstinline^on_arg_match^ is used implicitly whenever a callback is used without preceding match expression.

\clearpage
\subsection{Wildcards}
\label{Sec::PatternMatching::Wildcards}

The type \lstinline^anything^ can be used as wildcard to match any number of any types.
%The \lstinline^constexpr^ value \lstinline^any_vals^ can be used as function argument if \lstinline^on^ is used without template paremeters.
A pattern created by \lstinline^on<anything>()^ or its alias \lstinline^others^ is useful to define a default case.
For patterns defined without template parameters, the \lstinline^constexpr^ value \lstinline^any_vals^ can be used as function argument.
The constant \lstinline^any_vals^ is of type \lstinline^anything^ and is nothing but syntactic sugar for defining patterns.

\begin{lstlisting}[language=C++]
on<int, anything>() >> [](int i) {
  // tuple with int as first element
},
on(any_vals, arg_match) >> [](int i) {
  // tuple with int as last element
  // "on(any_vals, arg_match)" is equal to "on(anything{}, arg_match)"
},
others >> [] {
  // everything else (default handler)
  // "others" is equal to "on<anything>()" and "on(any_vals)"
}
\end{lstlisting}

\subsection{Projections}

Projections perform type conversions or extract data from a given input.
If a callback expects an integer but the received message contains a string, a projection can be used to perform a type conversion on-the-fly.
This conversion must not have side-effects and must not throw exceptions.
A failed projection is not an error, it simply indicates that a pattern is not matched.
Let us have a look at a simple example.

\begin{lstlisting}
auto intproj = [](const string& str) -> option<int> {
  char* endptr = nullptr;
  int result = static_cast<int>(strtol(str.c_str(), &endptr, 10));
  if (endptr != nullptr && *endptr == '\0') return result;
  return {};
};
message_handler fun {
  on(intproj) >> [](int i) {
    // case 1: successfully converted a string
  },
  [](const string& str) {
    // case 2: str is not an integer
  }
};
\end{lstlisting}

The lambda \lstinline^intproj^ is a \lstinline^string^ $\Rightarrow$ \lstinline^int^ projection, but note that it does not return an integer.
It returns \lstinline^option<int>^, because the projection is not guaranteed to always succeed.
An empty \lstinline^option^ indicates, that a value does not have a valid mapping to an integer.
A pattern does not match if a projection failed.

\textbf{Note}: Functors used as projection must take exactly one argument and must return a value.
The types for the pattern are deduced from the functor's signature.
If the functor returns an \lstinline^option<T>^, then \lstinline^T^ is deduced.

\subsection{Dynamically Building Messages}

Usually, messages are created implicitly when sending messages but can also be created explicitly using \lstinline^make_message^.
In both cases, types and number of elements are known at compile time.
To allow for fully dynamic message generation, \lib also offers a third option to create messages by using a \lstinline^message_builder^:

\begin{lstlisting}
message_builder mb;
// prefix message with some atom
mb.append(strings_atom::value);
// fill message with some strings
std::vector<std::string> strings{/*...*/};
for (auto& str : strings) {
  mb.append(str);
}
// create the message
message msg = mb.to_message();
\end{lstlisting}
