summaryrefslogtreecommitdiff
path: root/pypers/pycon10/talk.html
diff options
context:
space:
mode:
Diffstat (limited to 'pypers/pycon10/talk.html')
-rw-r--r--pypers/pycon10/talk.html824
1 files changed, 824 insertions, 0 deletions
diff --git a/pypers/pycon10/talk.html b/pypers/pycon10/talk.html
new file mode 100644
index 0000000..44f1c21
--- /dev/null
+++ b/pypers/pycon10/talk.html
@@ -0,0 +1,824 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.5: http://docutils.sourceforge.net/" />
+<meta name="version" content="S5 1.1" />
+<title>Introduction to Functional Programming</title>
+<meta name="date" content="2010-05-08" />
+<style type="text/css">
+
+/*
+:Author: David Goodger (goodger@python.org)
+:Id: $Id: html4css1.css 5196 2007-06-03 20:25:28Z wiemann $
+:Copyright: This stylesheet has been placed in the public domain.
+
+Default cascading style sheet for the HTML output of Docutils.
+
+See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
+customize this style sheet.
+*/
+
+/* used to remove borders from tables and images */
+.borderless, table.borderless td, table.borderless th {
+ border: 0 }
+
+table.borderless td, table.borderless th {
+ /* Override padding for "table.docutils td" with "! important".
+ The right padding separates the table cells. */
+ padding: 0 0.5em 0 0 ! important }
+
+.first {
+ /* Override more specific margin styles with "! important". */
+ margin-top: 0 ! important }
+
+.last, .with-subtitle {
+ margin-bottom: 0 ! important }
+
+.hidden {
+ display: none }
+
+a.toc-backref {
+ text-decoration: none ;
+ color: black }
+
+blockquote.epigraph {
+ margin: 2em 5em ; }
+
+dl.docutils dd {
+ margin-bottom: 0.5em }
+
+/* Uncomment (and remove this text!) to get bold-faced definition list terms
+dl.docutils dt {
+ font-weight: bold }
+*/
+
+div.abstract {
+ margin: 2em 5em }
+
+div.abstract p.topic-title {
+ font-weight: bold ;
+ text-align: center }
+
+div.admonition, div.attention, div.caution, div.danger, div.error,
+div.hint, div.important, div.note, div.tip, div.warning {
+ margin: 2em ;
+ border: medium outset ;
+ padding: 1em }
+
+div.admonition p.admonition-title, div.hint p.admonition-title,
+div.important p.admonition-title, div.note p.admonition-title,
+div.tip p.admonition-title {
+ font-weight: bold ;
+ font-family: sans-serif }
+
+div.attention p.admonition-title, div.caution p.admonition-title,
+div.danger p.admonition-title, div.error p.admonition-title,
+div.warning p.admonition-title {
+ color: red ;
+ font-weight: bold ;
+ font-family: sans-serif }
+
+/* Uncomment (and remove this text!) to get reduced vertical space in
+ compound paragraphs.
+div.compound .compound-first, div.compound .compound-middle {
+ margin-bottom: 0.5em }
+
+div.compound .compound-last, div.compound .compound-middle {
+ margin-top: 0.5em }
+*/
+
+div.dedication {
+ margin: 2em 5em ;
+ text-align: center ;
+ font-style: italic }
+
+div.dedication p.topic-title {
+ font-weight: bold ;
+ font-style: normal }
+
+div.figure {
+ margin-left: 2em ;
+ margin-right: 2em }
+
+div.footer, div.header {
+ clear: both;
+ font-size: smaller }
+
+div.line-block {
+ display: block ;
+ margin-top: 1em ;
+ margin-bottom: 1em }
+
+div.line-block div.line-block {
+ margin-top: 0 ;
+ margin-bottom: 0 ;
+ margin-left: 1.5em }
+
+div.sidebar {
+ margin: 0 0 0.5em 1em ;
+ border: medium outset ;
+ padding: 1em ;
+ background-color: #ffffee ;
+ width: 40% ;
+ float: right ;
+ clear: right }
+
+div.sidebar p.rubric {
+ font-family: sans-serif ;
+ font-size: medium }
+
+div.system-messages {
+ margin: 5em }
+
+div.system-messages h1 {
+ color: red }
+
+div.system-message {
+ border: medium outset ;
+ padding: 1em }
+
+div.system-message p.system-message-title {
+ color: red ;
+ font-weight: bold }
+
+div.topic {
+ margin: 2em }
+
+h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
+h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
+ margin-top: 0.4em }
+
+h1.title {
+ text-align: center }
+
+h2.subtitle {
+ text-align: center }
+
+hr.docutils {
+ width: 75% }
+
+img.align-left {
+ clear: left }
+
+img.align-right {
+ clear: right }
+
+ol.simple, ul.simple {
+ margin-bottom: 1em }
+
+ol.arabic {
+ list-style: decimal }
+
+ol.loweralpha {
+ list-style: lower-alpha }
+
+ol.upperalpha {
+ list-style: upper-alpha }
+
+ol.lowerroman {
+ list-style: lower-roman }
+
+ol.upperroman {
+ list-style: upper-roman }
+
+p.attribution {
+ text-align: right ;
+ margin-left: 50% }
+
+p.caption {
+ font-style: italic }
+
+p.credits {
+ font-style: italic ;
+ font-size: smaller }
+
+p.label {
+ white-space: nowrap }
+
+p.rubric {
+ font-weight: bold ;
+ font-size: larger ;
+ color: maroon ;
+ text-align: center }
+
+p.sidebar-title {
+ font-family: sans-serif ;
+ font-weight: bold ;
+ font-size: larger }
+
+p.sidebar-subtitle {
+ font-family: sans-serif ;
+ font-weight: bold }
+
+p.topic-title {
+ font-weight: bold }
+
+pre.address {
+ margin-bottom: 0 ;
+ margin-top: 0 ;
+ font-family: serif ;
+ font-size: 100% }
+
+pre.literal-block, pre.doctest-block {
+ margin-left: 2em ;
+ margin-right: 2em }
+
+span.classifier {
+ font-family: sans-serif ;
+ font-style: oblique }
+
+span.classifier-delimiter {
+ font-family: sans-serif ;
+ font-weight: bold }
+
+span.interpreted {
+ font-family: sans-serif }
+
+span.option {
+ white-space: nowrap }
+
+span.pre {
+ white-space: pre }
+
+span.problematic {
+ color: red }
+
+span.section-subtitle {
+ /* font-size relative to parent (h1..h6 element) */
+ font-size: 80% }
+
+table.citation {
+ border-left: solid 1px gray;
+ margin-left: 1px }
+
+table.docinfo {
+ margin: 2em 4em }
+
+table.docutils {
+ margin-top: 0.5em ;
+ margin-bottom: 0.5em }
+
+table.footnote {
+ border-left: solid 1px black;
+ margin-left: 1px }
+
+table.docutils td, table.docutils th,
+table.docinfo td, table.docinfo th {
+ padding-left: 0.5em ;
+ padding-right: 0.5em ;
+ vertical-align: top }
+
+table.docutils th.field-name, table.docinfo th.docinfo-name {
+ font-weight: bold ;
+ text-align: left ;
+ white-space: nowrap ;
+ padding-left: 0 }
+
+h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
+h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
+ font-size: 100% }
+
+ul.auto-toc {
+ list-style-type: none }
+
+</style>
+<!-- configuration parameters -->
+<meta name="defaultView" content="slideshow" />
+<meta name="controlVis" content="hidden" />
+<!-- style sheet links -->
+<script src="ui/default/slides.js" type="text/javascript"></script>
+<link rel="stylesheet" href="ui/default/slides.css"
+ type="text/css" media="projection" id="slideProj" />
+<link rel="stylesheet" href="ui/default/outline.css"
+ type="text/css" media="screen" id="outlineStyle" />
+<link rel="stylesheet" href="ui/default/print.css"
+ type="text/css" media="print" id="slidePrint" />
+<link rel="stylesheet" href="ui/default/opera.css"
+ type="text/css" media="projection" id="operaFix" />
+
+<style type="text/css">
+#currentSlide {display: none;}
+</style>
+</head>
+<body>
+<div class="layout">
+<div id="controls"></div>
+<div id="currentSlide"></div>
+<div id="header">
+
+</div>
+<div id="footer">
+<h1>Introduction to Functional Programming</h1>
+<h2>PyCon Italia 2010</h2>
+</div>
+</div>
+<div class="presentation">
+<div class="slide" id="slide0">
+<h1 class="title">Introduction to Functional Programming</h1>
+<table class="docinfo" frame="void" rules="none">
+<col class="docinfo-name" />
+<col class="docinfo-content" />
+<tbody valign="top">
+<tr class="field"><th class="docinfo-name">Event:</th><td class="field-body">PyCon Italia 2010</td>
+</tr>
+<tr class="field"><th class="docinfo-name">Presenters:</th><td class="field-body">Michele Simionato, Nicola Larosa</td>
+</tr>
+<tr><th class="docinfo-name">Date:</th>
+<td>2010-05-08</td></tr>
+</tbody>
+</table>
+<!-- Definitions of interpreted text roles (classes) for S5/HTML data. -->
+<!-- This data file has been placed in the public domain. -->
+<!-- Colours
+======= -->
+<!-- Text Sizes
+========== -->
+<!-- Display in Slides (Presentation Mode) Only
+========================================== -->
+<!-- Display in Outline Mode Only
+============================ -->
+<!-- Display in Print Only
+===================== -->
+<!-- Display in Handout Mode Only
+============================ -->
+<!-- Incremental Display
+=================== -->
+
+</div>
+<div class="slide" id="my-goals-for-this-talk">
+<h1>My goals for this talk</h1>
+<ul class="simple">
+<li>this is an introductory talk (no monads, no combinators,
+no pattern matching, no concurrency, no blurb)</li>
+<li>mostly about Python, with 1 or 2 examples in Scheme</li>
+<li>a first part for purists (rebinding and TCO)</li>
+<li>a second part focused on functional <em>design</em> in real life</li>
+<li>also a few remarks about functional aspects in automatic testing
+and database programming</li>
+</ul>
+</div>
+<div class="slide" id="first-two-misconceptions">
+<h1>First: two misconceptions</h1>
+<ul class="simple">
+<li>two extreme viewpoints:</li>
+</ul>
+<blockquote>
+<ol class="arabic simple">
+<li>FP means map, filter, reduce</li>
+<li>FP means Haskell</li>
+</ol>
+</blockquote>
+<ul class="incremental simple">
+<li>I am in between</li>
+<li>readability and maintainability are my first concerns, not purity</li>
+<li>... still purity is attractive</li>
+</ul>
+</div>
+<div class="slide" id="what-functional-means">
+<h1>What functional means</h1>
+<ul>
+<li><p class="first">a lot of emphasis on the functions in the past, nowadays people stress
+more the data structures</p>
+</li>
+<li><p class="first">a language is functional if</p>
+<blockquote>
+<ol class="incremental arabic simple">
+<li><em>variables cannot be re-assigned</em></li>
+<li><em>data structures cannot be modified</em></li>
+<li><em>I/O side effects are confined</em></li>
+</ol>
+</blockquote>
+</li>
+</ul>
+</div>
+<div class="slide" id="less-is-more">
+<h1>Less is more</h1>
+<ul class="simple">
+<li>FP is about having <em>less</em> features, not more!</li>
+</ul>
+<ul class="incremental simple">
+<li>less ways of shooting yourself in the foot</li>
+<li>the functional programmer is often compared to a monk</li>
+<li>the challenge: can we program under such strong constraints??</li>
+</ul>
+</div>
+<div class="slide" id="point-1-immutable-bindings">
+<h1>Point 1: immutable bindings</h1>
+<ul class="simple">
+<li>there are no more variables as we intend them</li>
+<li>what about for loops?</li>
+</ul>
+<pre class="doctest-block">
+&gt;&gt;&gt; for item in sequence:
+ do_something(item)
+</pre>
+<ul class="incremental simple">
+<li>the name <tt class="docutils literal"><span class="pre">item</span></tt> is rebound at each iteration</li>
+<li>(talk about boxes and labels)</li>
+<li>for loops have worked well for 50+ years, it seems impossible to
+live without them</li>
+<li>... but do for loops work really well?</li>
+</ul>
+</div>
+<div class="slide" id="let-s-see">
+<h1>Let's see ...</h1>
+<pre class="literal-block">
+root = Tkinter.Tk()
+text = Tkinter.StringVar()
+label = Tkinter.Label(root, textvariable=text)
+menubar = Tkinter.Menu(root)
+menu = Tkinter.Menu(menubar)
+menubar.add_cascade(label='File', menu=menu)
+for item in ['F1','F2', 'F3']:
+ def showmenu():
+ text.set(text.get() + '\n%s' % item)
+ menu.add_command(label=item, command=showmenu)
+root.config(menu=menubar); label.pack()
+root.mainloop()
+</pre>
+</div>
+<div class="slide" id="the-usual-hack">
+<h1>The usual hack</h1>
+<pre class="literal-block">
+root = Tkinter.Tk()
+text = Tkinter.StringVar()
+label = Tkinter.Label(root, textvariable=text)
+menubar = Tkinter.Menu(root)
+menu = Tkinter.Menu(menubar)
+menubar.add_cascade(label='File', menu=menu)
+for item in ['F1','F2', 'F3']:
+ def showmenu(item=item):
+ text.set(text.get() + '\n%s' % item)
+ menu.add_command(label=item, command=showmenu)
+root.config(menu=menubar); label.pack()
+root.mainloop()
+</pre>
+</div>
+<div class="slide" id="this-is-still-a-hack">
+<h1>This is still a hack</h1>
+<ul class="simple">
+<li>looking at the interaction of for-loops and closures is a good
+test to see if a language is functional</li>
+</ul>
+<ul class="incremental simple">
+<li>this is an example of the difference between a truly functional language
+and an imperative language with some support for FP</li>
+<li>Python, Common Lisp, Go do <em>not</em> pass the test</li>
+<li>Haskell, Scheme, Clojure, Perl <em>do</em> pass the test</li>
+</ul>
+</div>
+<div class="slide" id="a-simpler-example">
+<h1>A simpler example</h1>
+<pre class="literal-block">
+lst = []
+for i in 0, 1, 2:
+ def f():
+ print i
+ lst.append(f)
+
+lst[0]() #=&gt; 2
+lst[1]() #=&gt; 2
+lst[2]() #=&gt; 2
+</pre>
+</div>
+<div class="slide" id="a-partial-solution">
+<h1>A partial solution</h1>
+<pre class="literal-block">
+lst = []
+def append_f(i):
+ def f():
+ print i
+ lst.append(f)
+
+for i in 0, 1, 2: # mutation is still there
+ append_f(i)
+
+lst[0]() #=&gt; 0
+lst[1]() #=&gt; 1
+lst[2]() #=&gt; 2
+</pre>
+</div>
+<div class="slide" id="the-question">
+<h1>The question</h1>
+<p>We need a way to compute a loop <em>without</em> rebinding the loop variable:</p>
+<pre class="literal-block">
+def loop123():
+ for i in 1, 2, 3:
+ &lt;do_something(i)&gt;
+
+loop123()
+</pre>
+<p>Clearly we need to introduce a new scope at each iteration</p>
+</div>
+<div class="slide" id="the-answer-recursion">
+<h1>The answer: recursion</h1>
+<p>Convert the function containing a loop in a recursive function with an
+additional argument (the loop index):</p>
+<pre class="literal-block">
+def loop123(i=1):
+ if i &gt; 3:
+ return
+ else:
+ &lt;do_something(i)&gt;
+ loop123(i+1) # tail call
+
+loop123()
+</pre>
+</div>
+<div class="slide" id="another-example-enumerate">
+<h1>Another example: enumerate</h1>
+<p>Here is an example of a for loop used to build a data structure:</p>
+<pre class="literal-block">
+def enumerate(values, i=0, acc=()):
+ if i &gt;= len(values):
+ return acc
+ else:
+ return enumerate(
+ values, i+1, acc + ((i, values[i]),))
+</pre>
+<p>The trick is to use an (immutable) accumulator</p>
+</div>
+<div class="slide" id="the-importance-of-tail-calls">
+<h1>The importance of tail calls</h1>
+<ul class="simple">
+<li>in a truly functional language all for-loops are implemented as
+recursive functions in tail call form</li>
+</ul>
+<ul class="incremental simple">
+<li>the compiler is able to recognize them and avoids creating
+a new stack per each iteration (TCO): no recursion limit</li>
+<li>for the programmer POV the loop variable is never reassigned</li>
+<li>it seems <em>perverse</em> but it is essential</li>
+<li>expecially for things like pattern matching</li>
+</ul>
+</div>
+<div class="slide" id="a-note-on-pattern-matching">
+<h1>A note on pattern matching</h1>
+<p>Pattern matching is used a lot in functional languages; in Scheme is
+especially used in macro programming; in ML and Haskell is used everywhere,
+even to define functions:</p>
+<pre class="literal-block">
+fun fact n = fact' (n, 1)
+and fact' (0, acc) = acc
+ | fact' (n, acc) = fact' (n-1, acc*n);
+</pre>
+<p>In Erlang is used to destructure the messages sent to the Erlang lightweight
+processes.</p>
+</div>
+<div class="slide" id="tco-and-debugging">
+<h1>TCO and debugging</h1>
+<p>There has been some heated debate last year due to Guido's dismissal
+of TCO.</p>
+<p class="incremental">In all fairness I must notice that TCO does not prevent debugging:</p>
+<pre class="incremental literal-block">
+;; tco.ss
+(let loop ((x -3))
+ (/ 1 x)
+ (loop (add1 x)))
+</pre>
+<p class="incremental">(but I agree that iterative is better than recursive)</p>
+</div>
+<div class="slide" id="the-pragmatist-voice">
+<h1>The pragmatist voice</h1>
+<p><em>Python programs written in functional style usually won’t go to the
+extreme of avoiding all I/O or all assignments; instead, they’ll
+provide a functional-appearing interface but will use non-functional
+features internally. For example, the implementation of a function
+will still use assignments to local variables, but won’t modify global
+variables or have other side effects.</em> -- Andrew Kuchling</p>
+</div>
+<div class="slide" id="example-collecting-objects">
+<h1>Example: collecting objects</h1>
+<pre class="literal-block">
+def collect_mail(mails):
+ storage = {}
+ for mail in mails:
+ client = mail.getclient()
+ kind = mail.getkind()
+ date = mail.getdate()
+ stored = storage.get((client, kind))
+ if stored is None or stored.date &lt; date:
+ storage[client, kind] = mail
+ return storage
+</pre>
+</div>
+<div class="slide" id="for-purists-at-all-costs">
+<h1>For purists at all costs ...</h1>
+<ul>
+<li><p class="first">you can avoid mutation of the storage by introducting a functional
+update utility:</p>
+<pre class="literal-block">
+def update(d, k, v):
+ newd = d.copy()
+ newd.update({k : v})
+ return newd
+</pre>
+</li>
+</ul>
+</div>
+<div class="slide" id="use-a-helper-function">
+<h1>... use a helper function</h1>
+<pre class="literal-block">
+def _collect_mail(storage, mail):
+ # a left-folding function: acc,obj-&gt;new-acc
+ client = mail.getclient()
+ kind = mail.getkind()
+ date = mail.getdate()
+ stored = storage.get((client, kind))
+ if stored is None or stored.date &lt; date:
+ return update(
+ storage, (client, kind), mail)
+ else:
+ return storage
+</pre>
+</div>
+<div class="slide" id="then-reduce-is-your-friend">
+<h1>... then reduce is your friend</h1>
+<pre class="literal-block">
+def collect_mail(mails):
+ return reduce(_collect_mail, mails, {})
+</pre>
+<ul class="incremental simple">
+<li>except that you should not be <em>perverse</em></li>
+<li>there is no reason to be functional at any cost if you are using a
+non-functional language</li>
+<li>do not fight the language, flow with it</li>
+<li>and this close the discussion about immutable bindings</li>
+</ul>
+</div>
+<div class="slide" id="point-2-immutable-data">
+<h1>Point 2: immutable data</h1>
+<ul class="simple">
+<li>we cannot really get rid of all mutable objects but
+certainly mutable objects are overused</li>
+</ul>
+<ul class="incremental simple">
+<li>mutable objects are often evil
+(globals, example of nosetests changing my sys.path)</li>
+<li>mutable objects can be often avoided
+(functional update may substitute mutation)</li>
+<li>there are smart functional data structures nowadays
+(not much in Python)</li>
+<li>Python has only strings, (named)tuples and frozensets</li>
+</ul>
+</div>
+<div class="slide" id="namedtuple">
+<h1>namedtuple</h1>
+<pre class="doctest-block">
+&gt;&gt;&gt; from collections import namedtuple
+&gt;&gt;&gt; Point = namedtuple('Point', 'x y')
+&gt;&gt;&gt; p1 = Point(0, 0)
+&gt;&gt;&gt; p2 = p1._replace(x=1)
+&gt;&gt;&gt; p2
+(1, 0)
+&gt;&gt;&gt; p1 is p2
+False
+</pre>
+<p>(requires copying the full structure in Python). Python also lacks
+immutable dictionaries (say Red/Black trees).</p>
+</div>
+<div class="slide" id="generators-are-mutable">
+<h1>Generators are mutable</h1>
+<p>Many Python programs (especially the ones using list/generator
+comprehension and the itertools module) are considered in functional
+style even if they are not functional from a purist POV:</p>
+<blockquote>
+<pre class="doctest-block">
+&gt;&gt;&gt; it123 = iter([1, 2, 3])
+&gt;&gt;&gt; for i in it123: print i,
+...
+1 2 3
+&gt;&gt;&gt; for i in it123: print i,
+...
+</pre>
+</blockquote>
+</div>
+<div class="slide" id="the-functional-way-streams">
+<h1>The functional way: streams</h1>
+<p>Looping over a stream does not mutate it:</p>
+<pre class="literal-block">
+&gt; (import (srfi :41 streams))
+&gt; (define str123 (stream-range 1 4))
+&gt; (stream-for-each display str123)
+123
+&gt; (stream-for-each display str123)
+123
+</pre>
+<p>Yet another difference between Python and a true functional language</p>
+</div>
+<div class="slide" id="confined-side-effects">
+<h1>3: confined side effects?</h1>
+<ul>
+<li><p class="first">to be able to distinguish pure functions from
+impure functions is important:</p>
+<pre class="literal-block">
+&#64;memoize
+def do_something():
+ result = long_computation()
+ log.info('Computed %s', result)
+ return result
+</pre>
+</li>
+<li><p class="first">Haskell is the purest language when it comes to
+confining side effects</p>
+</li>
+</ul>
+</div>
+<div class="slide" id="side-effects-and-unittests">
+<h1>Side effects and unittests</h1>
+<ul class="simple">
+<li>in Python keeping the distinction between pure and impure functions is a
+question of good coding style</li>
+</ul>
+<ul class="incremental simple">
+<li>common sense tells you that you should decouple I/O from the
+business logic</li>
+<li>unit testing is arguably the master path to functional design:
+if you want to test a thing, make it a pure function</li>
+<li>if it is difficult to test it is not functional</li>
+</ul>
+</div>
+<div class="slide" id="usual-recommendations">
+<h1>Usual recommendations</h1>
+<p>All the usual recommendations to make code more testable, such as</p>
+<ul class="incremental simple">
+<li>avoid side effects (including the ones at import time)</li>
+<li>do not use special variables (damned them!)</li>
+<li>decouple the system i.e. pass objects around</li>
+<li>write libraries, not frameworks</li>
+<li>feel guilty!</li>
+</ul>
+<p>are recommendations to make code more functional.</p>
+</div>
+<div class="slide" id="database-connections-bad">
+<h1>Database connections (bad)</h1>
+<p>db = DBSession() # singleton</p>
+<dl class="docutils">
+<dt>def read(...):</dt>
+<dd>db.read_data( ... )</dd>
+<dt>def write(data, ...):</dt>
+<dd>db.write_data(data, ...)</dd>
+<dt>if __name__ == '__main__':</dt>
+<dd>db.init(dsn)</dd>
+</dl>
+</div>
+<div class="slide" id="database-connections-good">
+<h1>Database connections (good)</h1>
+<dl class="docutils">
+<dt>def read(db, ...):</dt>
+<dd>db.read_data( ... )</dd>
+<dt>def write(db, data, ...):</dt>
+<dd>db.write_data(data, ...)</dd>
+<dt>if __name__ == '__main__':</dt>
+<dd>db = DBSession(dsn)</dd>
+</dl>
+</div>
+<div class="slide" id="fp-and-databases">
+<h1>FP and databases</h1>
+<ul class="simple">
+<li>operating on a DB looks like the least functional thing you can do
+(ex. <tt class="docutils literal"><span class="pre">importer.import(fileobj,</span> <span class="pre">db)</span></tt>)</li>
+</ul>
+<ul class="incremental">
+<li><p class="first">still can be made functional, at the price of <em>creating the db</em>
+(this is how we write the db tests):</p>
+<pre class="literal-block">
+def import(lines): # this is a pure function!
+ db = create_db()
+ out = importer.import(lines, db)
+ drop_db(db)
+ return out
+</pre>
+</li>
+</ul>
+</div>
+<div class="slide" id="functional-design-and-sql">
+<h1>Functional design and SQL</h1>
+<ul class="simple">
+<li>SQL makes a good functional language once you remove mutation
+(UPDATE and DELETE)</li>
+</ul>
+<ul class="incremental simple">
+<li>SELECTs are not really different from list comprehensions
+(think of LINQ);</li>
+<li>if you can use a view, use it (tell my recent experience making legacy
+SQL code more functional)</li>
+<li>even non-premature optimizations are evil :-(</li>
+</ul>
+</div>
+<div class="slide" id="references">
+<h1>References</h1>
+<p><a class="reference external" href="http://www.phyast.pitt.edu/~micheles/scheme/TheAdventuresofaPythonistainSchemeland.pdf">http://www.phyast.pitt.edu/~micheles/scheme/TheAdventuresofaPythonistainSchemeland.pdf</a>
+<a class="reference external" href="http://www.haskell.org/">http://www.haskell.org/</a>
+<a class="reference external" href="http://clojure.org/">http://clojure.org/</a>
+<a class="reference external" href="http://docs.python.org/howto/functional.html">http://docs.python.org/howto/functional.html</a>
+<a class="reference external" href="http://www.defmacro.org/ramblings/fp.html">http://www.defmacro.org/ramblings/fp.html</a>
+<a class="reference external" href="http://www.cs.cmu.edu/~rwh/theses/okasaki.pdf">http://www.cs.cmu.edu/~rwh/theses/okasaki.pdf</a>
+<a class="reference external" href="http://srfi.schemers.org/srfi-41/srfi-41.html">http://srfi.schemers.org/srfi-41/srfi-41.html</a>
+<a class="reference external" href="http://funcall.blogspot.com/2009/05/you-knew-id-say-something-part-iv.html">http://funcall.blogspot.com/2009/05/you-knew-id-say-something-part-iv.html</a></p>
+</div>
+</div>
+</body>
+</html>