wtfunctional/tex/wtfunctional.tex

535 lines
16 KiB
TeX
Raw Normal View History

\documentclass[english]{beamer}
\usepackage{babel}
\usepackage{csquotes}
\usepackage{tabularx}
2016-04-25 16:20:31 +02:00
\usepackage[backend=biber,]{biblatex}
\bibliography{wtf}
\renewcommand{\bibfont}{\small}
\usepackage{fontspec}
\setsansfont{Fira Sans}
\setmonofont{Inconsolata-g}
\usetheme{Antibes}
\setbeamercovered{transparent}
\newcommand{\cpp}{\texttt{C++}}
\title{WTFunctional}
\author{Oliver Rümpelein}
\subtitle{Using functional structures in non-functional languages}
\input{headers/listings}
\begin{document}
\frame{\titlepage}
\begin{frame}[plain]{What?}
\begin{enumerate}[<+->]
\item Dafunc? Introduction to functional paradigms using Haskell
\item PhuncY! Functional programming in Python
\item Fun\cpp{}tional: STL-hacks and usage in \cpp
\end{enumerate}
\begin{uncoverenv}<4-| invisible@1-3>
\emph{With preview to \cpp{}17/20/22!}
\end{uncoverenv}
\end{frame}
\section{Dafunc?}
\subsection{Functional programming}
\begin{frame}{Understanding functional paradigms}
Here: so called \enquote{purely functional} paradigm.
\begin{itemize}
\item<+-> Programming without \enquote{side-effects}
\begin{itemize}
\item<+-> No mutability
\item<+-> Functions work only in local context
\end{itemize}
\item<+-> Extensive use of lists and so called maps/reduces (later)
\item<+-> Do not mix up with \enquote{procedural} programming (using only functions)!
\end{itemize}
\end{frame}
\begin{frame}[fragile]{Example}
2016-04-25 16:20:31 +02:00
% ToDo: C-code call by value, call by reference.
\begin{cppcode}
int f(int x) { return ++x;}
int g(int& x) { return ++x;}
int main() {
int x = 2;
f(x);
assert(x==2); // f is “functional”
g(x);
assert(x!=2); // g is not!
}
\end{cppcode}
\end{frame}
\begin{frame}{Pros and Cons}
Pros:
\begin{itemize}[<+->]
\item Maintainability
\item Testing
\item (often) shorter code
\end{itemize}
Cons:
\begin{itemize}[<+->]
\item harder to learn
\item harder to understand
\item slower due to abstraction
\end{itemize}
\end{frame}
\subsection{Case study: Haskell}
\begin{frame}{Overview}
\begin{itemize}[<+->]
\item \emph{Haskell} is a purely functional, compiled programming language
developed since 1990.
\item It is typed and has a strong meta-type system (comparable to
interfaces in OOP)
\item The most important implementation is \emph{GHC} (Glasgow Haskell
Compiler)
\item Haskell is lazy. Statements get evaluated only when needed, if ever.
\end{itemize}
\end{frame}
\begin{frame}[fragile]{Syntax Functions}
Function constraints, definition and calls:
2016-04-25 16:20:31 +02:00
\begin{haskell}
mysum :: Num a => a -> a -> a -> a
mysum x y z = x + y + z
-- b == 6
b = mysum 1 2 3
\end{haskell}
\pause
Functions always get evaluated left to right, thus the following works (\emph{Currying}):
2016-04-25 16:20:31 +02:00
\begin{haskell}
mysum2 = mysum 2
-- c == 12
c = mysum2 4 6
\end{haskell}
\end{frame}
\begin{frame}[fragile]{Syntax Lists (1)}
\begin{itemize}[<+->]
\item Lists in Haskell can only hold data of one type. They are defined using
\haskellcmd{a = [1,2,3,4]} or similar.
\item An automatic range can be obtained by using \haskellcmd{b = [1..4]},
where the last number is inclusive.
\item If possible, Haskell will try to inhibit the step
automatically. \haskellcmd{c = [1,3..7]} yields
\haskellcmd{[1,3,5,7]}.
\item When leaving out the end specifier, a range can be infinite. In this case,
it's up to the programmer to constrain things.
\end{itemize}
\end{frame}
\begin{frame}[fragile]{Syntax Lists (2)}
\begin{itemize}[<+->]
\item Two lists can be concatenated using the \haskellcmd{++} operator:
\haskellcmd{[1,2,3] ++ [4..7]}
\item Single objects get pushed to the front using
2016-04-25 16:20:31 +02:00
\enquote{\haskellcmd{:}}: \haskellcmd{1:[2..7]}.
\item This can also be used vice versa to extract single values from lists:
2016-04-25 16:20:31 +02:00
\begin{haskell}
extract (x:xs) = x
-- a = 1
a = extract [1..5]
\end{haskell}
\end{itemize}
\end{frame}
2016-04-25 16:20:31 +02:00
\begin{frame}[fragile]{Syntax Recursion}
Example: Add a value to every entry in an array
2016-04-25 16:20:31 +02:00
\begin{haskell}
addto :: (Num a) => [a] -> a -> [a]
addto [] _ = [] -- edge case (list empty)
addto (x:xs) y = (x+y) : addto xs y
b = [1..4]
-- c == [5,6,7,8]
c = addto b 4
\end{haskell}
\end{frame}
\begin{frame}[fragile]{Lambdas}
\begin{itemize}[<+->]
\item By now: lambda-functions well known from other programming languages
\item Represent \enquote{anonymous} functions, i.e. locally defined functions
without associated name
\item Can simply be passed to algorithms, i.e. sort.
\item Syntax: \haskellcmd{\var1 var2 -> retval}
\end{itemize}
\end{frame}
\begin{frame}[fragile]{Maps, Filters}
\begin{itemize}[<+->]
\item A \emph{Map} applies a function to all elements of a list:
\haskellcmd{map (^2) c}\quad (square the elements of c)
\item A \emph{Filter} does exactly that to a list:
\haskellcmd{filter (\x -> (mod x 2) == 0) c} \quad (even numbers in c,
filtering done using a lambda function)
\end{itemize}
\end{frame}
\begin{frame}[fragile]{Folds (1)}
\begin{itemize}[<+->]
\item \emph{Folds} (or sometimes \emph{reductions}) create single values
using whole lists, i.e. sums over all elements
\item Often implemented using recursion
\item Need a function, an initialization value and a list
\end{itemize}
\end{frame}
\begin{frame}[fragile]{Folds (2)}
\uncover<+-> Example: Self written right fold and sum:
2016-04-25 16:20:31 +02:00
\begin{haskell}
mfold f z [] = z
mfold f z (x:xs) = f x (mfold f z xs)
msum = mfold (+) 0
-- g == 5050
g = msum [1..100]
\end{haskell}
\uncover<+->{Note that this gets pretty resource hungry with large
lists, better use left-folds for this (see~\cite{whichfold})}
\end{frame}
\begin{frame}[fragile]{Example: Pythagorean triangles}
Get all Pythagorean triangles with a hypotenuse off length at most 15:
2016-04-25 16:20:31 +02:00
\begin{haskell}
> [(a,b,c) | a <- [1..15],
b <- [1..a],
c <- [1..b],
a^2 == b^2 + c^2]
2016-04-25 16:20:31 +02:00
[(5,4,3),(10,8,6),(13,12,5),(15,12,9)]
\end{haskell}
\end{frame}
\begin{frame}[fragile]{Example: Bubble-sort}
Recursive, functional bubble-sort algorithm:
2016-04-25 16:20:31 +02:00
\begin{haskell}
bsort f [] = []
bsort f (x:xs) = (bsort f a) ++ [x] ++ (bsort f b)
where a = [ y | y <- xs, not (f x y) ]
b = [ y | y <- xs, (f x y) ]
2016-04-25 16:20:31 +02:00
mbsort = bsort (\x y -> (x > y))
\end{haskell}
\pause Result:
2016-04-25 16:20:31 +02:00
\begin{haskell}
λ> h = [1, 20, -10, 5]
λ> mbsort h
[-10,1,5,29]
\end{haskell}
\end{frame}
\section{PhuncY!}
2016-04-25 16:20:31 +02:00
\subsection{Overview}
\begin{frame}{Functional programming in Python}
\begin{itemize}[<+->]
\item Obviously, python is not strictly functional…
\item …but has functions as first class objects!
\item Some other stuff is widely used, but with another syntax…
\item …, although there are ways to get the \enquote{real} functional
style.
\item I use python3 here, python2 differs in some points.
\end{itemize}
\end{frame}
\subsection{Elements}
2016-04-25 16:20:31 +02:00
\begin{frame}[fragile]{Lambdas, Maps}
\begin{itemize}[<+->]
\item Lambda-syntax: \pycmd{lambda a,b: a+b}
\item Maps are done by \pycmd{map}
\item \emph{Note:} Most functional list-functions return iterators in
python, not lists!
\item Use \pycmd{list()} to cast Iterators, but this is usually not
necessary.
\end{itemize}
\end{frame}
\begin{frame}[fragile]{Filters}
\begin{itemize}[<+->]
\item Can be done using \pycmd{filter(func, iter)}:
\begin{pycode}
a = range(1,7)
b = filter(lambda x: x%2, a)
print(list(b))
# [1,3,5]
\end{pycode}
\item Alternatively, use List Comprehension:
\begin{pycode}
a = range(1,7)
b = [x for x in a if x%2]
print(b)
\end{pycode}
\item Pro: Maybe easier readable, returns list
\item Con: Returns list (slower when iterating afterwards)
\end{itemize}
\end{frame}
\begin{frame}[fragile]{Fold}
\begin{itemize}[<+->]
\item From the python2 to python3 Changelog:
\begin{quote}
Removed `reduce()`. Use `functools.reduce()` if you really need it;
however, 99 percent of the time an explicit `for` loop is more
readable.
\end{quote}
\item I disagree Old-style is more explicit and still available from \pycmd{functools}
\item Example sum of squares
\begin{pycode}
from functools import reduce
a = range(10)
mapped = map(lambda x: x**2, a)
reduced = reduce(lambda x,y: x+y, mapped)
\end{pycode}
\end{itemize}
\end{frame}
\begin{frame}[fragile]{Currying}
\begin{itemize}[<+->]
\item No real currying, but several workarounds
\item Lambdas: \pycmd{g=lambda x: foo(2,x)}
\item \pycmd{functools.partial}:
\begin{pycode}
def foo(x,y):
return x+y
bar=partial(foo, 2)
bar(3) # 5
\end{pycode}
\end{itemize}
\end{frame}
\begin{frame}{Decorators (1)}
2016-04-25 16:20:31 +02:00
\begin{itemize}[<+->]
\item Often used to modify functions in Frameworks
\item Basic pattern: Decorator is a function that itself takes a function,
and returns a wrapper
\item Step-by-step introduction to decorators at~\cite{decorators}
\end{itemize}
\end{frame}
\begin{frame}[fragile]{Decorators (2)}
2016-04-25 16:20:31 +02:00
\begin{pycode}
def debug(func):
def inner(*args, **kwargs):
print("F: {}, args: {}, kwargs: {}\n"
.format(func.__name__, args, kwargs))
return func(*args, **kwargs)
2016-04-25 16:20:31 +02:00
return inner
2016-04-25 16:20:31 +02:00
@debug
def foo(x):
pass
foo(2) # => F: foo, args: (2), kwargs: {}
2016-04-25 16:20:31 +02:00
\end{pycode}
\end{frame}
\subsection{Conclusion}
\begin{frame}{Quite enough…}
\begin{itemize}[<+->]
\item Python is not really functional…
\item …but is strongly influenced by functional paradigms.
\item Its functional parts are heavily used, i.e in Genomics
\end{itemize}
\end{frame}
\begin{frame}[fragile]{Example}
\begin{pycode}
def mybubblesort(array,
func=lambda x, y: True if x > y else False):
if (len(array) == 0):
return []
else:
x, *xs = array
return mybubblesort([y for y in xs
if func(x,y)], func) \
+ [x] \
+ mybubblesort([y for y in xs \
if not func(x,y)], func)
\end{pycode}
\end{frame}
\section{Fun\cpp{}ional}
\subsection{Overview}
\begin{frame}{Functional programming in \cpp{}}
\begin{itemize}[<+->]
\item \enquote{Classical} \cpp{} has a few functional elements…
\item …but lacks lambdas, for instance.
\item This changed with the modern standards, starting from \cpp{}11.
\end{itemize}
\end{frame}
\subsection{Elements}
\begin{frame}[fragile]{Lists}
\begin{itemize}[<+->]
\item In \cpp{}, \emph{Iterators} are equivalent to lists in functional languages.
\item Examples of iterators include \cppcmd{vector} and \cppcmd{array}.
\item See~\cite{cppiter} for more information about the specific iterator
types and the prerequisites they bring.
\end{itemize}
\end{frame}
\begin{frame}[fragile]{lambdas}
\begin{itemize}[<+->]
\item \emph{Lambdas} have been introduced with \cpp{}11
\item Syntax:
\begin{cppcode}
[v1,&v2](int v1, int v2)
{return v1 < v2}
\end{cppcode}
\item The \cppcmd{[]} denotes the capture-list and specifies, whether
variables are used by value or by reference. If this is empty,
anything is used by value.
\item Lambdas are fully-featured \emph{functionals}, such are functions
wrapped with \cppcmd{std::function}, and objects implementing
\cppcmd{operator()}.
\end{itemize}
\end{frame}
\begin{frame}[fragile]{Maps (1)}
\uncover<+->{\begin{alertblock}{map ≠ map}
\cppcmd{std::map} is a data-type similar to pythons \pycmd{dict} and has no
relation to the functional concept of maps!
\end{alertblock}}
\uncover<+->{The following can be used instead (both from \cppcmd{<algorithm>}):}
\begin{itemize}[<+->]
\item \cppcmd{std::for_each}
\item \cppcmd{std::transform}
2016-04-25 16:20:31 +02:00
\end{itemize}
\uncover<+->{But they are quite different.}
\end{frame}
\begin{frame}[fragile]{Maps (2)}
\uncover<+->{\cppcmd{std::for_each} applies a function \cppcmd{void fun(T &a)} to elements
of an iterator containing values of type \cppcmd{T} in place:}
\begin{uncoverenv}<+->
\begin{cppcode}
vector<int> a{1,2,3};
for_each(a.begin(), a.end(),
[](int &n){ n*=2; });
\end{cppcode}
\end{uncoverenv}
\uncover<+->{This multiplies each element in \cppcmd{a} by 2.}
\end{frame}
\begin{frame}[fragile]{Maps (3)}
\uncover<+->{In contrast, \cppcmd{std::transform} returns a new iterator containing type
\cppcmd{U}. Thus, the function has to be \cppcmd{U func(T val)}:}
\begin{uncoverenv}<+->
\begin{cppcode}
vector<int> b{1,2,3,4};
vector<double> c(b.size(), 0.0);
transform(b.begin(), b.end(), c.begin(),
[](int i){ return 1.0/i; });
\end{cppcode}
\end{uncoverenv}
\uncover<+->{This gives a vector c filled with the inverse elements of b.}
\uncover<+->{There are also forms of \cppcmd{transform} that merge two
iterators (see examples in git-repo).}
\end{frame}
\begin{frame}[fragile]{Filters}
\begin{itemize}[<+->]
\item This is ugly
\item No syntactic sugar as with python's list comprehensions
\item Use \cppcmd{std::remove_if} or \cppcmd{std::remove_copy_if} from \cppcmd{<algorithm>},
\item afterwards \cppcmd{transform}.
\item Or make use of the \cppcmd{boost::filter_iterator} library.
\end{itemize}
\end{frame}
\begin{frame}[fragile]{Folds}
\begin{itemize}[<+->]
\item \cppcmd{std::accumulate} is defined in \cppcmd{<numeric>}
\item Takes bounds of an Iterator, and a \cppcmd{BinaryOperation}
\item Example:
\begin{cppcode}
vector<int> a{1,2,3,4}
int b = accumulate(a.begin(), a.end(), 0); // sum
int c = accumulate(a.begin(), a.end(), 15, minus<int>());
\end{cppcode}
\cppcmd{std::minus<int>} is defined in \cppcmd{<numeric>} as well.
\end{itemize}
\end{frame}
\begin{frame}[fragile]{Generics and \texttt{D}}
\begin{itemize}[<+->]
\item These are only procedural examples of functional programming.
\item Much can be done using \emph{generic} techniques
(\enquote{templates}).
\item Many examples: \cite{generics}
\item Much more to come in \cpp{}20/22 (\cite[What will Not make it into
C+17,…]{cpp17})
\begin{itemize}[<+->]
\item \emph{Concepts} are kind of constraints on template parameters.
\item \emph{Ranges} will replace iterators
\item All of the above and more are available in the \texttt{D}
programming language! (\url{dlang.org})
\end{itemize}
\end{itemize}
\end{frame}
\begin{frame}[fragile]{Generics example: Folds}
\begin{uncoverenv}<+->
Using \cpp{}11 with variadic templates, one has (mod \cppcmd{auto})
\begin{cppcode}
auto sum() { return 0; }
template<typename T>
auto sum(T t) { return t; }
template<typename T, typename... Ts>
auto sum(T t, Ts... ts) { return t + sum(ts...); }
\end{cppcode}
\end{uncoverenv}
\begin{uncoverenv}<+->
With new folding expression (\cite{cppfolds}):
\begin{cppcode}
template<typename T>
auto sum(const auto&... args)
{ return (args + ...); }
\end{cppcode}
\end{uncoverenv}
\end{frame}
\begin{frame}[plain]{References}
\printbibliography
2016-04-25 16:20:31 +02:00
\end{frame}
\section{The}
\subsection{end}
\begin{frame}[plain]{Thanks for listening!}{Any questions?}
\href{https://git.f3l.de/pheerai/wtfunctional/}{Git-Repo with examples and
slides}: \url{git.f3l.de/pheerai/wtfunctional/}
\begin{description}
\item[Mail:] \url{oli_r@fg4f.de}
\item[XMPP:] \url{pheerai@im.f3l.de}
\item[Github:] \href{https://github.com/pheerai/}{pheerai}
\item[Misc:] Signal, Telegram,…
\item[…or] later having some drink
\end{description}
\vfill
\tiny \raggedleft Proudly typed using Lua\LaTeX{}. Slides-theme: \emph{Antibes}\\
Fonts used are \href{github.com/mozilla/Fira}{\emph{Fira Sans}} and
\href{leonardo-m.livejournal.com/77079.html}{\emph{Inconsolata G}}.\\
Syntax and code highlighting with
\href{https://github.com/gpoore/minted}{\emph{minted}} and
\href{http://pygments.org}{\emph{pygments}}.
\end{frame}
\end{document}
%%% Local Variables:
%%% mode: latex
2016-04-25 16:20:31 +02:00
%%% ispell-local-dictionary: "en_GB"
%%% End: