167 lines
3.6 KiB
TeX
167 lines
3.6 KiB
TeX
\begin{frame}
|
|
\frametitle{Interlude: Generalization}
|
|
|
|
\begin{itemize}
|
|
\item All generated code must never refer to specific implementations.
|
|
\item Whether or not a specific component is implemented should be determined at compile time.
|
|
\end{itemize}
|
|
\end{frame}
|
|
|
|
\begin{frame}[fragile]
|
|
\frametitle{Traits}
|
|
|
|
\begin{itemize}
|
|
\item Traits are interfaces; describe a set of methods.
|
|
\item Traits are constraints; they limit function input.
|
|
\item Traits are markers; they can indicate certain properties.
|
|
\end{itemize}
|
|
|
|
\begin{center}
|
|
\begin{BVerbatim}[fontsize=\small]
|
|
trait Iterator {
|
|
type Item;
|
|
fn next(&mut self) -> Option<Self::Item>;
|
|
}
|
|
fn for_each<I, T, F>(mut iter: I, func: F)
|
|
where I: Iterator<Item=T>, F: Fn(T) {
|
|
loop {
|
|
match iter.next() {
|
|
Some(next) => func(next),
|
|
None => return,
|
|
}
|
|
}
|
|
}
|
|
\end{BVerbatim}
|
|
\end{center}
|
|
\end{frame}
|
|
|
|
\begin{frame}[fragile]
|
|
\frametitle{How can we use traits to our advantage?}
|
|
|
|
\begin{itemize}
|
|
\item Have a \texttt{Backend} trait to represent different backends
|
|
\end{itemize}
|
|
|
|
\begin{center}
|
|
\begin{BVerbatim}
|
|
trait Backend {
|
|
fn func1(...) -> (...);
|
|
}
|
|
\end{BVerbatim}
|
|
\end{center}
|
|
\end{frame}
|
|
|
|
\begin{frame}[fragile]
|
|
\frametitle{How can we use traits to our advantage?}
|
|
|
|
\begin{itemize}
|
|
\item Have a \texttt{Component} trait to represent different components
|
|
\item \texttt{Component}s are \textit{parameterized} by backends
|
|
\end{itemize}
|
|
|
|
\begin{center}
|
|
\begin{BVerbatim}
|
|
trait Component<B: Backend> {
|
|
fn foo(...) -> Bar;
|
|
}
|
|
\end{BVerbatim}
|
|
\end{center}
|
|
\end{frame}
|
|
|
|
\begin{frame}[fragile]
|
|
\frametitle{How can we use traits to our advantage?}
|
|
|
|
\begin{itemize}
|
|
\item Individual components implement a trait on a specific backend.
|
|
\item If there's no implementation, the compile will fail.
|
|
\end{itemize}
|
|
|
|
\begin{center}
|
|
\begin{BVerbatim}
|
|
struct InputBox {
|
|
some_field_1: SomeType1,
|
|
some_field_2: SomeType2,
|
|
}
|
|
|
|
// Now we can use InputBox for web targets!
|
|
impl Component<Web> for InputBox {
|
|
fn foo(...) -> Bar {
|
|
(...)
|
|
}
|
|
}
|
|
\end{BVerbatim}
|
|
\end{center}
|
|
\end{frame}
|
|
|
|
\begin{frame}[fragile]
|
|
\frametitle{It's not that easy...}
|
|
|
|
\begin{itemize}
|
|
\item \textbf{Problem:} all backends now share the same data structure.
|
|
\item A web input box needs different data than a native one.
|
|
\end{itemize}
|
|
|
|
\begin{columns}
|
|
\begin{column}{0.4\textwidth}
|
|
\begin{Verbatim}
|
|
struct InputBoxWeb {
|
|
web_ref: Reference,
|
|
}
|
|
\end{Verbatim}
|
|
\end{column}
|
|
\begin{column}{0.4\textwidth}
|
|
\begin{Verbatim}
|
|
struct InputBoxNative {
|
|
gl_ctx: GlContext,
|
|
}
|
|
\end{Verbatim}
|
|
\end{column}
|
|
\end{columns}
|
|
\end{frame}
|
|
|
|
\begin{frame}[fragile]
|
|
\frametitle{Don't limit components or backends}
|
|
|
|
We don't want to end up in a scenario where we're enumerating all backends or components. For example:
|
|
|
|
\vspace{1em}
|
|
\begin{columns}
|
|
\begin{column}{0.4\textwidth}
|
|
\begin{Verbatim}
|
|
enum InputBox {
|
|
Web(...),
|
|
Native(...),
|
|
...
|
|
}
|
|
\end{Verbatim}
|
|
|
|
\vspace{0.5em}
|
|
\small{What happens when we add a new backend?}
|
|
\end{column}
|
|
\begin{column}{0.4\textwidth}
|
|
\begin{Verbatim}
|
|
trait Backend {
|
|
type InputBox;
|
|
type Button;
|
|
...
|
|
}
|
|
\end{Verbatim}
|
|
|
|
\vspace{0.5em}
|
|
\small{What happens when we add a new component?}
|
|
\end{column}
|
|
\end{columns}
|
|
\end{frame}
|
|
|
|
\begin{frame}
|
|
\frametitle{Potential model}
|
|
|
|
\begin{center}
|
|
\includegraphics[width=.85\textwidth]{{./dot/component_backend.dot}.pdf}
|
|
\end{center}
|
|
|
|
\begin{itemize}
|
|
\item \small{How do we discover the concrete implementation from the abstract trait?}
|
|
\end{itemize}
|
|
\end{frame}
|
|
|