Finished first draft of Python-part.

This commit is contained in:
Oliver Rümpelein 2016-04-25 16:20:31 +02:00
parent 4110c30cc6
commit e59dac99bf
4 changed files with 193 additions and 79 deletions

View file

@ -19,22 +19,22 @@ html header: <link rel="stylesheet"
+ currying => just convenience + currying => just convenience
+ code example: Pythagoraian triangles, bubble sort + code example: Pythagoraian triangles, bubble sort
* Phuncy: The pythonic way is functional! * Phuncy: The pythonic way is functional!
- Not strictly functional + Not strictly functional
- recursion, fafco - recursion
- lambda syntax + fafco
- map, fold => example (sum of squares?) - map, fold => example (sum of squares?)
- python lambda syntax: lambda a,b: a+b + python lambda syntax: lambda a,b: a+b
- fold with reduce + don't return lists, but iterators!
- don't return lists, but iterators! + fold with reduce
- Note: 2: map, filter, reduce, list comprehension + Note: 2: map, filter, reduce, list comprehension
3: map, filter, functools.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; “Removed `reduce()`. Use `functools.reduce()` if you really need it;
however, 99 percent of the time an explicit `for` loop is more however, 99 percent of the time an explicit `for` loop is more
readable.” readable.”
- Why use it? => Multi-processing, WTF Count. + Why use it? => Multi-processing, WTF Count.
```python ```python
a = list(range(10)) a = list(range(10))
@ -50,7 +50,7 @@ html header: <link rel="stylesheet"
from functools import reduce from functools import reduce
print(reduce(lambda x,y: x+y,map(lambda x: x**2,range(10)))) print(reduce(lambda x,y: x+y,map(lambda x: x**2,range(10))))
``` ```
- currying: not really, but binding via lambdas or functools.partial() or + currying: not really, but binding via lambdas or functools.partial() or
https://mtomassoli.wordpress.com/2012/03/18/currying-in-python/ https://mtomassoli.wordpress.com/2012/03/18/currying-in-python/
- decorators! - decorators!
- still FP has advantages and is heavily used, i.e. in genomics (works on - still FP has advantages and is heavily used, i.e. in genomics (works on

View file

@ -39,9 +39,22 @@
fontsize=\small, fontsize=\small,
} }
\newminted[pycode]{python}%
{
linenos=true,
autogobble=true,
breaklines=true,
showspaces=false,
showtabs=false,
tabsize=2,
frame=single,
fontsize=\small,
}
\newmintinline[ccmd]{c}{} \newmintinline[ccmd]{c}{}
\newmintinline[cppcmd]{cpp}{} \newmintinline[cppcmd]{cpp}{}
\newmintinline[haskellcmd]{haskell}{} \newmintinline[haskellcmd]{haskell}{}
\newmintinline[pycmd]{python}{}
%%% Local Variables: %%% Local Variables:
%%% mode: latex %%% mode: latex

View file

@ -3,3 +3,9 @@ title={Foldr Foldl Foldl' - HaskellWiki},
urldate={2016-04-21}, urldate={2016-04-21},
url={https://wiki.haskell.org/Foldr_Foldl_Foldl%27}, url={https://wiki.haskell.org/Foldr_Foldl_Foldl%27},
} }
@online{decorators,
title={simeonfranklin.com - Understanding Python Decorators in 12 Easy Steps!},
urldate={2016-04-25},
url={http://simeonfranklin.com/blog/2012/jul/1/python-decorators-in-12-steps/},
}

View file

@ -3,7 +3,7 @@
\usepackage{babel} \usepackage{babel}
\usepackage{csquotes} \usepackage{csquotes}
\usepackage{tabularx} \usepackage{tabularx}
\usepackage[backend=biber, style=numeric,]{biblatex} \usepackage[backend=biber,]{biblatex}
\bibliography{wtf} \bibliography{wtf}
\usepackage{fontspec} \usepackage{fontspec}
@ -39,18 +39,18 @@
\end{frame} \end{frame}
\begin{frame}[fragile]{Example} \begin{frame}[fragile]{Example}
%ToDo: C-code call by value, call by reference. % ToDo: C-code call by value, call by reference.
\begin{cppcode} \begin{cppcode}
int f(int x) { return ++x;} int f(int x) { return ++x;}
int g(int& x) { return ++x;} int g(int& x) { return ++x;}
int main() { int main() {
int x = 2; int x = 2;
f(x); f(x);
assert(x==2); // f is “functional” assert(x==2); // f is “functional”
g(x); g(x);
assert(x!=2); // g is not! assert(x!=2); // g is not!
} }
\end{cppcode} \end{cppcode}
\end{frame} \end{frame}
\begin{frame}{Pros and Cons} \begin{frame}{Pros and Cons}
@ -83,19 +83,19 @@
\begin{frame}[fragile]{Syntax Functions} \begin{frame}[fragile]{Syntax Functions}
Function constraints, definition and calls: Function constraints, definition and calls:
\begin{haskell} \begin{haskell}
mysum :: Num a => a -> a -> a -> a mysum :: Num a => a -> a -> a -> a
mysum x y z = x + y + z mysum x y z = x + y + z
-- b == 6 -- b == 6
b = mysum 1 2 3 b = mysum 1 2 3
\end{haskell} \end{haskell}
\pause \pause
Functions always get evaluated left to right, thus the following works (\emph{Currying}): Functions always get evaluated left to right, thus the following works (\emph{Currying}):
\begin{haskell} \begin{haskell}
mysum2 = mysum 2 mysum2 = mysum 2
-- c == 12 -- c == 12
c = mysum2 4 6 c = mysum2 4 6
\end{haskell} \end{haskell}
\end{frame} \end{frame}
\begin{frame}[fragile]{Syntax Lists (1)} \begin{frame}[fragile]{Syntax Lists (1)}
@ -119,24 +119,24 @@
\item Single objects get pushed to the front using \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: \item This can also be used vice versa to extract single values from lists:
\begin{haskell} \begin{haskell}
extract (x:xs) = x extract (x:xs) = x
-- a = 1 -- a = 1
a = extract [1..5] a = extract [1..5]
\end{haskell} \end{haskell}
\end{itemize} \end{itemize}
\end{frame} \end{frame}
\begin{frame}[fragile]{Syntax Recursion} \begin{frame}[fragile]{Syntax Recursion}
Example: Add a value to every entry in an array Example: Add a value to every entry in an array
\begin{haskell} \begin{haskell}
addto :: (Num a) => [a] -> a -> [a] addto :: (Num a) => [a] -> a -> [a]
addto [] _ = [] -- edge case (list empty) addto [] _ = [] -- edge case (list empty)
addto (x:xs) y = (x+y) : addto xs y addto (x:xs) y = (x+y) : addto xs y
b = [1..4] b = [1..4]
-- c == [5,6,7,8] -- c == [5,6,7,8]
c = addto b 4 c = addto b 4
\end{haskell} \end{haskell}
\end{frame} \end{frame}
\begin{frame}[fragile]{Lambdas} \begin{frame}[fragile]{Lambdas}
@ -170,43 +170,138 @@
\begin{frame}[fragile]{Folds (2)} \begin{frame}[fragile]{Folds (2)}
\uncover<+-> Example: Self written Right fold and sum: \uncover<+-> Example: Self written Right fold and sum:
\begin{haskell} \begin{haskell}
mfold f z [] = z mfold f z [] = z
mfold f z (x:xs) = f x (mfold f z xs) mfold f z (x:xs) = f x (mfold f z xs)
msum = mfold (+) 0 msum = mfold (+) 0
-- g == 5050 -- g == 5050
g = msum [1..100] g = msum [1..100]
\end{haskell} \end{haskell}
\uncover<+->{Note that this gets pretty resource hungry with large \uncover<+->{Note that this gets pretty resource hungry with large
lists, better use left-folds for this (see~\cite{whichfold})} lists, better use left-folds for this (see~\cite{whichfold})}
\end{frame} \end{frame}
\begin{frame}[fragile]{Example: Pythagorean triangles} \begin{frame}[fragile]{Example: Pythagorean triangles}
Get all Pythagorean triangles with a hypotenuse off length at most 15: Get all Pythagorean triangles with a hypotenuse off length at most 15:
\begin{haskell} \begin{haskell}
> [(a,b,c) | a <- [1..15], > [(a,b,c) | a <- [1..15],
b <- [1..a], b <- [1..a],
c <- [1..b], c <- [1..b],
a^2 == b^2 + c^2] a^2 == b^2 + c^2]
[(5,4,3),(10,8,6),(13,12,5),(15,12,9)] [(5,4,3),(10,8,6),(13,12,5),(15,12,9)]
\end{haskell} \end{haskell}
\end{frame} \end{frame}
\begin{frame}[fragile]{Example: Bubble-sort} \begin{frame}[fragile]{Example: Bubble-sort}
Recursive, functional bubble-sort algorithm: Recursive, functional bubble-sort algorithm:
\begin{haskell} \begin{haskell}
bsort f [] = [] bsort f [] = []
bsort f (x:xs) = (bsort f a) ++ [x] ++ (bsort f b) bsort f (x:xs) = (bsort f a) ++ [x] ++ (bsort f b)
where a = [ y | y <- xs, not (f x y) ] where a = [ y | y <- xs, not (f x y) ]
b = [ y | y <- xs, (f x y) ] b = [ y | y <- xs, (f x y) ]
mbsort = bsort (\x y -> (x > y)) mbsort = bsort (\x y -> (x > y))
\end{haskell} \end{haskell}
\pause Result: \pause Result:
\begin{haskell} \begin{haskell}
λ> h = [1, 20, -10, 5] λ> h = [1, 20, -10, 5]
λ> mbsort h λ> mbsort h
[-10,1,5,29] [-10,1,5,29]
\end{haskell} \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} \end{frame}
\begin{frame}[plain]{References} \begin{frame}[plain]{References}
@ -216,5 +311,5 @@
%%% Local Variables: %%% Local Variables:
%%% mode: latex %%% mode: latex
%%% ispell-dictionary: en %%% ispell-local-dictionary: "en_GB"
%%% End: %%% End: