\documentclass[english]{beamer} \usepackage{babel} \usepackage{csquotes} \usepackage{tabularx} \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} % 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: \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}): \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 \enquote{\haskellcmd{:}}: \haskellcmd{1:[2..7]}. \item This can also be used vice versa to extract single values from lists: \begin{haskell} extract (x:xs) = x -- a = 1 a = extract [1..5] \end{haskell} \end{itemize} \end{frame} \begin{frame}[fragile]{Syntax – Recursion} Example: Add a value to every entry in an array \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: \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: \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} \begin{frame}[fragile]{Example: Bubble-sort} Recursive, functional bubble-sort algorithm: \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} \pause Result: \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} \subsection{Elements} \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)} \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)} \begin{pycode} def debug(func): def inner(*args, **kwargs): print("F: {}, args: {}, kwargs: {}\n" .format(func.__name__, args, kwargs)) return func(*args, **kwargs) return inner @debug def foo(x): pass foo(2) # => F: foo, args: (2), kwargs: {} \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{}):} \begin{itemize}[<+->] \item \cppcmd{std::for_each} \item \cppcmd{std::transform} \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 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 b{1,2,3,4}; vector 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{}, \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{} \item Takes bounds of an Iterator, and a \cppcmd{BinaryOperation} \item Example: \begin{cppcode} vector a{1,2,3,4} int b = accumulate(a.begin(), a.end(), 0); // sum int c = accumulate(a.begin(), a.end(), 15, minus()); \end{cppcode} \cppcmd{std::minus} is defined in \cppcmd{} 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 auto sum(T t) { return t; } template 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 auto sum(const auto&... args) { return (args + ...); } \end{cppcode} \end{uncoverenv} \end{frame} \begin{frame}[plain]{References} \printbibliography \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 %%% ispell-local-dictionary: "en_GB" %%% End: