\documentclass[english]{beamer} \usepackage{babel} \usepackage{csquotes} \usepackage{tabularx} \usepackage[backend=biber,]{biblatex} \bibliography{wtf} \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} % 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} \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} \end{frame} \begin{frame}[plain]{References} \printbibliography \end{frame} \end{document} %%% Local Variables: %%% mode: latex %%% ispell-local-dictionary: "en_GB" %%% End: