diff --git a/Notes.md b/Notes.md
index 2306c19..3ea8333 100644
--- a/Notes.md
+++ b/Notes.md
@@ -19,22 +19,22 @@ html header: just convenience
+ code example: Pythagoraian triangles, bubble sort
* Phuncy: The pythonic way is functional!
- - Not strictly functional
- - recursion, fafco
- - lambda syntax
+ + Not strictly functional
+ - recursion
+ + fafco
- map, fold => example (sum of squares?)
- - python lambda syntax: lambda a,b: a+b
- - fold with reduce
- - don't return lists, but iterators!
- - Note: 2: map, filter, reduce, list comprehension
+ + python lambda syntax: lambda a,b: a+b
+ + don't return lists, but iterators!
+ + fold with reduce
+ + Note: 2: map, filter, reduce, list comprehension
3: map, filter, functools.reduce(), list comprehension
- - The python2 to 3 page states:
+ + The python2 to 3 page states:
“Removed `reduce()`. Use `functools.reduce()` if you really need it;
however, 99 percent of the time an explicit `for` loop is more
readable.”
- - Why use it? => Multi-processing, WTF Count.
+ + Why use it? => Multi-processing, WTF Count.
```python
a = list(range(10))
@@ -50,7 +50,7 @@ html header: a -> a -> a -> a
- mysum x y z = x + y + z
- -- b == 6
- b = mysum 1 2 3
- \end{haskell}
+\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}
+\begin{haskell}
+mysum2 = mysum 2
+-- c == 12
+c = mysum2 4 6
+\end{haskell}
\end{frame}
\begin{frame}[fragile]{Syntax – Lists (1)}
@@ -117,26 +117,26 @@
\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]}.
+ \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}
+\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}
+\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}
@@ -169,52 +169,147 @@
\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<+-> 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{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}
+\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}
+\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{frame}
\end{document}
%%% Local Variables:
%%% mode: latex
-%%% ispell-dictionary: en
+%%% ispell-local-dictionary: "en_GB"
%%% End:
\ No newline at end of file