2016-04-20 12:26:05 +02:00
|
|
|
|
\documentclass[english]{beamer}
|
|
|
|
|
|
|
|
|
|
\usepackage{babel}
|
|
|
|
|
\usepackage{csquotes}
|
|
|
|
|
\usepackage{tabularx}
|
2016-04-25 16:20:31 +02:00
|
|
|
|
\usepackage[backend=biber,]{biblatex}
|
2016-04-21 15:57:27 +02:00
|
|
|
|
\bibliography{wtf}
|
2016-04-20 12:26:05 +02:00
|
|
|
|
|
|
|
|
|
\usepackage{fontspec}
|
|
|
|
|
\setsansfont{Fira Sans}
|
|
|
|
|
\setmonofont{Inconsolata-g}
|
|
|
|
|
|
|
|
|
|
\usetheme{Antibes}
|
|
|
|
|
%\usecolortheme{beaver}
|
|
|
|
|
\setbeamercovered{transparent}
|
|
|
|
|
|
|
|
|
|
\title{WTFunctional}
|
|
|
|
|
\author{Oliver Rümpelein}
|
|
|
|
|
\subtitle{Using functional structures in non-functional languages}
|
|
|
|
|
|
|
|
|
|
\input{headers/listings}
|
|
|
|
|
|
|
|
|
|
\begin{document}
|
|
|
|
|
\frame{\titlepage}
|
|
|
|
|
|
|
|
|
|
\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}
|
2016-04-20 12:26:05 +02:00
|
|
|
|
\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}
|
2016-04-20 12:26:05 +02:00
|
|
|
|
\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}
|
2016-04-20 12:26:05 +02:00
|
|
|
|
\end{frame}
|
|
|
|
|
|
|
|
|
|
\begin{frame}[fragile]{Syntax – Lists (1)}
|
2016-04-21 15:57:27 +02:00
|
|
|
|
\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}
|
2016-04-20 12:26:05 +02:00
|
|
|
|
\end{frame}
|
|
|
|
|
|
|
|
|
|
\begin{frame}[fragile]{Syntax – Lists (2)}
|
2016-04-21 15:57:27 +02:00
|
|
|
|
\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]}.
|
2016-04-21 15:57:27 +02:00
|
|
|
|
\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}
|
2016-04-21 15:57:27 +02:00
|
|
|
|
\end{itemize}
|
2016-04-20 12:26:05 +02:00
|
|
|
|
\end{frame}
|
2016-04-25 16:20:31 +02:00
|
|
|
|
|
2016-04-20 12:26:05 +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}
|
2016-04-20 12:26:05 +02:00
|
|
|
|
\end{frame}
|
2016-04-21 15:57:27 +02:00
|
|
|
|
|
|
|
|
|
\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)}
|
2016-04-25 16:20:31 +02:00
|
|
|
|
\uncover<+-> Example: Self written Right fold and sum:
|
|
|
|
|
\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}
|
2016-04-21 15:57:27 +02:00
|
|
|
|
\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]
|
|
|
|
|
[(5,4,3),(10,8,6),(13,12,5),(15,12,9)]
|
|
|
|
|
\end{haskell}
|
|
|
|
|
\end{frame}
|
2016-04-21 15:57:27 +02:00
|
|
|
|
|
|
|
|
|
\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) ]
|
|
|
|
|
mbsort = bsort (\x y -> (x > y))
|
|
|
|
|
\end{haskell}
|
2016-04-21 15:57:27 +02:00
|
|
|
|
\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!}
|
|
|
|
|
\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}
|
|
|
|
|
|
|
|
|
|
\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}[fragile]{Decorators}
|
|
|
|
|
\begin{itemize}[<+->]
|
|
|
|
|
\item Often used to modify functions in Frameworks
|
|
|
|
|
\item Encapsulates other functions. More infos at \cite{decorators}
|
|
|
|
|
\begin{pycode}
|
|
|
|
|
def debug(func):
|
|
|
|
|
def inner(*args, **kwargs):
|
|
|
|
|
sys.stderr.write("F: {}, args: {}, kwargs {}".format(func.__name__, args,
|
|
|
|
|
kwargs))
|
|
|
|
|
return func(*args, **args)
|
|
|
|
|
return inner
|
|
|
|
|
@debug
|
|
|
|
|
def foo(x):
|
|
|
|
|
print(x)
|
|
|
|
|
\end{pycode}
|
|
|
|
|
\end{itemize}
|
2016-04-21 15:57:27 +02:00
|
|
|
|
\end{frame}
|
|
|
|
|
|
|
|
|
|
\begin{frame}[plain]{References}
|
|
|
|
|
\printbibliography
|
2016-04-25 16:20:31 +02:00
|
|
|
|
\end{frame}
|
2016-04-20 12:26:05 +02:00
|
|
|
|
\end{document}
|
|
|
|
|
|
|
|
|
|
%%% Local Variables:
|
|
|
|
|
%%% mode: latex
|
2016-04-25 16:20:31 +02:00
|
|
|
|
%%% ispell-local-dictionary: "en_GB"
|
2016-04-20 12:26:05 +02:00
|
|
|
|
%%% End:
|