Finished first draft of Python-part.
This commit is contained in:
parent
4110c30cc6
commit
e59dac99bf
4 changed files with 193 additions and 79 deletions
20
Notes.md
20
Notes.md
|
@ -19,22 +19,22 @@ html header: <link rel="stylesheet"
|
|||
+ currying => 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: <link rel="stylesheet"
|
|||
from functools import reduce
|
||||
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/
|
||||
- decorators!
|
||||
- still FP has advantages and is heavily used, i.e. in genomics (works on
|
||||
|
|
|
@ -39,9 +39,22 @@
|
|||
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[cppcmd]{cpp}{}
|
||||
\newmintinline[haskellcmd]{haskell}{}
|
||||
\newmintinline[pycmd]{python}{}
|
||||
|
||||
%%% Local Variables:
|
||||
%%% mode: latex
|
||||
|
|
|
@ -3,3 +3,9 @@ title={Foldr Foldl Foldl' - HaskellWiki},
|
|||
urldate={2016-04-21},
|
||||
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/},
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
\usepackage{babel}
|
||||
\usepackage{csquotes}
|
||||
\usepackage{tabularx}
|
||||
\usepackage[backend=biber, style=numeric,]{biblatex}
|
||||
\usepackage[backend=biber,]{biblatex}
|
||||
\bibliography{wtf}
|
||||
|
||||
\usepackage{fontspec}
|
||||
|
@ -39,18 +39,18 @@
|
|||
\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}
|
||||
% 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}
|
||||
|
@ -83,19 +83,19 @@
|
|||
|
||||
\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}
|
||||
\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)}
|
||||
|
@ -119,24 +119,24 @@
|
|||
\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}
|
||||
\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}
|
||||
|
@ -170,43 +170,138 @@
|
|||
|
||||
\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}
|
||||
\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}
|
||||
\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}
|
||||
|
@ -216,5 +311,5 @@
|
|||
|
||||
%%% Local Variables:
|
||||
%%% mode: latex
|
||||
%%% ispell-dictionary: en
|
||||
%%% ispell-local-dictionary: "en_GB"
|
||||
%%% End:
|
Loading…
Reference in a new issue