summaryrefslogtreecommitdiff
path: root/pypers
diff options
context:
space:
mode:
authormsimionato <msimionato@msimionato.uxmi.statnet.statpro.com>2010-05-10 17:27:53 +0200
committermsimionato <msimionato@msimionato.uxmi.statnet.statpro.com>2010-05-10 17:27:53 +0200
commitbcfdacd57f45f049f9f54d7074389d0bf8e596f7 (patch)
tree59b8e9e3bd65381ed47964cf0e80717702957484 /pypers
parentb055201ebb7686783c0be59078a7bd540715c785 (diff)
downloadmicheles-bcfdacd57f45f049f9f54d7074389d0bf8e596f7.tar.gz
Added my talks at PyConIt 2010
Diffstat (limited to 'pypers')
-rw-r--r--pypers/pycon10/abstract.txt29
-rw-r--r--pypers/pycon10/cloc-trunk.txt42
-rw-r--r--pypers/pycon10/for_rec.py16
-rw-r--r--pypers/pycon10/menu1.py13
-rw-r--r--pypers/pycon10/menu2.py13
-rw-r--r--pypers/pycon10/recruiting.txt145
-rw-r--r--pypers/pycon10/statpro-home-page.pngbin0 -> 248968 bytes
-rw-r--r--pypers/pycon10/stream-ex.ss7
-rw-r--r--pypers/pycon10/talk.html824
-rw-r--r--pypers/pycon10/talk.txt487
-rw-r--r--pypers/pycon10/tco.py4
-rw-r--r--pypers/pycon10/tco.ss4
12 files changed, 1584 insertions, 0 deletions
diff --git a/pypers/pycon10/abstract.txt b/pypers/pycon10/abstract.txt
new file mode 100644
index 0000000..84c6335
--- /dev/null
+++ b/pypers/pycon10/abstract.txt
@@ -0,0 +1,29 @@
+;; This buffer is for notes you don't want to save, and for Lisp evaluation.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer.
+
+Introduzione alla programmazione funzionale
+---------------------------------------------------------
+
+In questo talk interattivo io e Nicola Larosa cercheremo di illustrare
+cosa significa "pensare in maniera funzionale" quando si lavora
+in un linguaggio come Python che funzionale non e'.
+
+In primo luogo cercheremo di sfatare alcuni luoghi comuni sulla
+programmazione funzionale (programmare funzionalmente NON vuol
+dire usare map, filter e reduce). In secondo luogo mostreremo
+vari errori comuni che non si commetterebbero se si pensasse in
+maniera piu' funzionale (mutare variabili globali, basarsi su effetti
+collaterali, eccetera). La terza parte del talk sara' un po' piu'
+esplorativa, mostrando qualche scorcio del vasto mondo funzionale
+che esiste al di fuori di Python: in particolare mostreremo le
+differenze tra un linguaggio con qualche supporto per la
+programmazione funzionale (come Python) ed un "vero" linguaggio funzionale.
+
+Lo scopo del talk e' quello di illustrare tecniche che permettono
+di scrivere codice piu' semplice e piu' manutenibile, non quello
+di decantare le virtu' della programmazione funzionale ad ogni
+costo. Non ci interessa spiegare come convertire tutti i for loop
+in chiamate ricorsive: l'interessante e' discutere come
+utilizzare un design funzionale piuttosto che uno basato su
+mutazione ed effetti collaterali.
diff --git a/pypers/pycon10/cloc-trunk.txt b/pypers/pycon10/cloc-trunk.txt
new file mode 100644
index 0000000..50e22ab
--- /dev/null
+++ b/pypers/pycon10/cloc-trunk.txt
@@ -0,0 +1,42 @@
+~$ cloc trunk
+ 11719 text files.
+ 11356 unique files.
+ 41343 files ignored.
+
+http://cloc.sourceforge.net v 1.08 T=125.0 s (73.9 files/s, 17064.8 lines/s)
+--------------------------------------------------------------------------------
+Language files blank comment code scale 3rd gen. equiv
+--------------------------------------------------------------------------------
+C++ 1694 77757 53011 340336 x 1.51 = 513907.36
+XML 574 2940 2554 249269 x 1.90 = 473611.10
+ASP 788 45807 4748 245940 x 1.29 = 317262.60
+Python 1986 38493 44093 176747 x 4.20 = 742337.40
+C/C++ Header 2349 57741 78168 160979 x 1.00 = 160979.00
+Javascript 173 26941 10581 121496 x 1.48 = 179814.08
+SQL 452 20768 4852 104580 x 2.29 = 239488.20
+C 334 14465 12988 99273 x 0.77 = 76440.21
+C# 104 4454 2502 27524 x 1.36 = 37432.64
+CSS 116 1618 1087 23786 x 1.00 = 23786.00
+Visual Basic 33 4130 5800 14136 x 2.76 = 39015.36
+make 269 1714 752 8978 x 2.50 = 22445.00
+Bourne Shell 51 598 1284 6556 x 3.81 = 24978.36
+m4 27 591 627 5552 x 1.00 = 5552.00
+MSBuild scripts 9 2 7 4878 x 1.90 = 9268.20
+IDL 23 592 0 3784 x 3.80 = 14379.20
+HTML 32 330 76 3767 x 1.90 = 7157.30
+Lisp 33 561 648 2702 x 1.25 = 3377.50
+DOS Batch 83 915 463 1159 x 0.63 = 730.17
+Ruby 13 272 97 1141 x 4.20 = 4792.20
+Perl 6 104 131 922 x 4.00 = 3688.00
+Java 3 131 173 534 x 1.36 = 726.24
+XSD 6 0 0 506 x 1.90 = 961.40
+awk 5 65 17 366 x 3.81 = 1394.46
+DTD 4 117 50 351 x 1.90 = 666.90
+ASP.Net 45 186 714 330 x 1.29 = 425.70
+Bourne Again Shell 12 63 8 245 x 3.81 = 933.45
+XSLT 1 15 14 196 x 1.90 = 372.40
+NAnt scripts 3 27 0 119 x 1.90 = 226.10
+Teamcenter def 10 16 0 93 x 1.00 = 93.00
+--------------------------------------------------------------------------------
+SUM: 9238 301413 225445 1606245 x 1.81 = 2906241.53
+--------------------------------------------------------------------------------
diff --git a/pypers/pycon10/for_rec.py b/pypers/pycon10/for_rec.py
new file mode 100644
index 0000000..166a67d
--- /dev/null
+++ b/pypers/pycon10/for_rec.py
@@ -0,0 +1,16 @@
+def loop123():
+ for i in 1, 2, 3:
+ # .....
+ print i
+ # .....
+
+def loop123(i=1):
+ if i > 3:
+ return
+ else:
+ # .....
+ print i
+ # .....
+ loop123(i+1)
+
+loop123()
diff --git a/pypers/pycon10/menu1.py b/pypers/pycon10/menu1.py
new file mode 100644
index 0000000..3259c32
--- /dev/null
+++ b/pypers/pycon10/menu1.py
@@ -0,0 +1,13 @@
+import Tkinter
+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()
diff --git a/pypers/pycon10/menu2.py b/pypers/pycon10/menu2.py
new file mode 100644
index 0000000..d148389
--- /dev/null
+++ b/pypers/pycon10/menu2.py
@@ -0,0 +1,13 @@
+import Tkinter
+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()
diff --git a/pypers/pycon10/recruiting.txt b/pypers/pycon10/recruiting.txt
new file mode 100644
index 0000000..694bc20
--- /dev/null
+++ b/pypers/pycon10/recruiting.txt
@@ -0,0 +1,145 @@
+StatPro
+----------------------------------
+
+.. image:: statpro-home-page.png
+
+Cloc
+--------------------------
+
+::
+
+ ~$ cloc trunk
+ 11719 text files.
+ 11356 unique files.
+ 41343 files ignored.
+
+ http://cloc.sourceforge.net v 1.08 T=125.0 s (73.9 files/s, 17064.8 lines/s)
+ --------------------------------------------------------------------------------
+ Language files blank comment code scale 3rd gen. equiv
+ --------------------------------------------------------------------------------
+ C++ 1694 77757 53011 340336 x 1.51 = 513907.36
+ XML 574 2940 2554 249269 x 1.90 = 473611.10
+ ASP 788 45807 4748 245940 x 1.29 = 317262.60
+ Python 1986 38493 44093 176747 x 4.20 = 742337.40
+ C/C++ Header 2349 57741 78168 160979 x 1.00 = 160979.00
+ Javascript 173 26941 10581 121496 x 1.48 = 179814.08
+ SQL 452 20768 4852 104580 x 2.29 = 239488.20
+ C 334 14465 12988 99273 x 0.77 = 76440.21
+ C# 104 4454 2502 27524 x 1.36 = 37432.64
+ CSS 116 1618 1087 23786 x 1.00 = 23786.00
+ Visual Basic 33 4130 5800 14136 x 2.76 = 39015.36
+ make 269 1714 752 8978 x 2.50 = 22445.00
+ Bourne Shell 51 598 1284 6556 x 3.81 = 24978.36
+ m4 27 591 627 5552 x 1.00 = 5552.00
+ MSBuild scripts 9 2 7 4878 x 1.90 = 9268.20
+ IDL 23 592 0 3784 x 3.80 = 14379.20
+ HTML 32 330 76 3767 x 1.90 = 7157.30
+ Lisp 33 561 648 2702 x 1.25 = 3377.50
+ DOS Batch 83 915 463 1159 x 0.63 = 730.17
+ Ruby 13 272 97 1141 x 4.20 = 4792.20
+ Perl 6 104 131 922 x 4.00 = 3688.00
+ Java 3 131 173 534 x 1.36 = 726.24
+ XSD 6 0 0 506 x 1.90 = 961.40
+ awk 5 65 17 366 x 3.81 = 1394.46
+ DTD 4 117 50 351 x 1.90 = 666.90
+ ASP.Net 45 186 714 330 x 1.29 = 425.70
+ Bourne Again Shell 12 63 8 245 x 3.81 = 933.45
+ XSLT 1 15 14 196 x 1.90 = 372.40
+ NAnt scripts 3 27 0 119 x 1.90 = 226.10
+ Teamcenter def 10 16 0 93 x 1.00 = 93.00
+ --------------------------------------------------------------------------------
+ SUM: 9238 301413 225445 1606245 x 1.81 = 2906241.53
+ --------------------------------------------------------------------------------
+
+Tecnologie che usiamo
+---------------------
+
+*troppe!*
+
+.. class:: incremental
+
+ + Python (2.5)
+ + SQLAlchemy
+ + Pylons
+ + Mako
+ + Zope/Plone
+ + Twisted
+
+... lato python
+---------------
+
+.. class:: incremental
+
+ + ipython
+ + virtualenv
+ + easy_install
+ + nosetests
+ + pylint/pyflakes
+ + matplotlib
+ + tutti quelli che ha menzionato Raymond e non solo
+
+Non di solo Python ...
+-----------------------
+
+ + C++
+ + swig
+
+ + ExtJS
+ + JQuery
+ + Flash
+
+ + XML
+ + SQLite
+
+Lato Linux
+----------
+
+ + PostgreSQL
+ + Grid engine
+ + sfs
+ + emacs
+ + vi
+ + ...
+
+Lato Windows
+------------
+
+ + SQLServer
+ + CORBA
+ + COM
+ + VB6/ASP
+ + VC++
+ + ...
+
+Organigramma di Milano
+-------------------------------------
+
+.. class:: incremental
+
++ Quants 3 (+1)
++ Techs 5 (+1)
++ BCD 2
++ SysAdmin 1
++ Customer support 1
++ Data Management Team 6
++ venditori, manager, segretaria, etc
+
+Requisiti
+-------------------------
+
+- sul sito c'e' la descrizione ufficiale della figura professionale ricercata:
+ ignoratela!
+
+.. class:: incremental
+
+- basta che sia bravo!
+
+- non si fanno distinzioni di genere, razza o nazionalita'
+
+Non siate timiti
+-----------------------------
+
+- se avete collaborato/collaborate a progetti open source, ditelo
+- se siete esperti di qualunque linguaggio esotico, ditelo
+- mandate i curriculum a luca.fittabile@statpro.com
+- se siete esperti di finanza invece a marco.marchioro@statpro.com
diff --git a/pypers/pycon10/statpro-home-page.png b/pypers/pycon10/statpro-home-page.png
new file mode 100644
index 0000000..02f8e7d
--- /dev/null
+++ b/pypers/pycon10/statpro-home-page.png
Binary files differ
diff --git a/pypers/pycon10/stream-ex.ss b/pypers/pycon10/stream-ex.ss
new file mode 100644
index 0000000..4ae56c3
--- /dev/null
+++ b/pypers/pycon10/stream-ex.ss
@@ -0,0 +1,7 @@
+(import (rnrs) (srfi :41 streams))
+
+(define str123 (stream-range 1 4))
+
+(stream-for-each display str123)
+
+(stream-for-each display str123)
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>
diff --git a/pypers/pycon10/talk.txt b/pypers/pycon10/talk.txt
new file mode 100644
index 0000000..181ba14
--- /dev/null
+++ b/pypers/pycon10/talk.txt
@@ -0,0 +1,487 @@
+Introduction to Functional Programming
+===============================================
+
+:Event: PyCon Italia 2010
+:Presenters: Michele Simionato, Nicola Larosa
+:Date: 2010-05-08
+
+.. include:: <s5defs.txt>
+.. footer:: PyCon Italia 2010
+
+My goals for this talk
+------------------------------------------------------
+
+- this is an introductory talk (no monads, no combinators,
+ no pattern matching, no concurrency, no blurb)
+- mostly about Python, with 1 or 2 examples in Scheme
+- a first part for purists (rebinding and TCO)
+- a second part focused on functional *design* in real life
+- also a few remarks about functional aspects in automatic testing
+ and database programming
+
+First: two misconceptions
+----------------------------------------
+
+- two extreme viewpoints:
+
+ 1. FP means map, filter, reduce
+ 2. FP means Haskell
+
+.. class:: incremental
+
+- I am in between
+- readability and maintainability are my first concerns, not purity
+- ... still purity is attractive
+
+What functional means
+------------------------
+
+- a lot of emphasis on the functions in the past, nowadays people stress
+ more the data structures
+
+- a language is functional if
+
+ .. class:: incremental
+
+ 1. *variables cannot be re-assigned*
+ 2. *data structures cannot be modified*
+ 3. *I/O side effects are confined*
+
+Less is more
+----------------------------------------------
+
+- FP is about having *less* features, not more!
+
+.. class:: incremental
+
+- less ways of shooting yourself in the foot
+- the functional programmer is often compared to a monk
+- the challenge: can we program under such strong constraints??
+
+1: immutable bindings
+--------------------------------------
+
+- there are no more variables as we intend them
+- what about for loops?
+
+>>> for item in sequence:
+ do_something(item)
+
+.. class:: incremental
+
+- the name ``item`` is rebound at each iteration
+- (talk about boxes and labels)
+- for loops have worked well for 50+ years, it seems impossible to
+ live without them
+- ... but do for loops work really well?
+
+Let's see ...
+----------------------------------------
+
+::
+
+ 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()
+
+The usual hack
+---------------------------------------
+
+::
+
+ 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()
+
+This is still a hack
+--------------------------------------------------
+
+- looking at the interaction of for-loops and closures is a good
+ test to see if a language is functional
+
+.. class:: incremental
+
+- this is an example of the difference between a truly functional language
+ and an imperative language with some support for FP
+- Python, Common Lisp, Go do *not* pass the test
+- Haskell, Scheme, Clojure, Perl *do* pass the test
+
+A simpler example
+----------------------------------------------
+
+::
+
+ lst = []
+ for i in 0, 1, 2:
+ def f():
+ print i
+ lst.append(f)
+
+ lst[0]() #=> 2
+ lst[1]() #=> 2
+ lst[2]() #=> 2
+
+A partial solution
+---------------------------------
+
+::
+
+ 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]() #=> 0
+ lst[1]() #=> 1
+ lst[2]() #=> 2
+
+The question
+---------------------------------
+
+We need a way to compute a loop *without* rebinding the loop variable::
+
+ def loop123():
+ for i in 1, 2, 3:
+ <do_something(i)>
+
+ loop123()
+
+Clearly we need to introduce a new scope at each iteration
+
+The answer: recursion
+---------------------------------
+
+Convert the function containing a loop in a recursive function with an
+additional argument (the loop index)::
+
+ def loop123(i=1):
+ if i > 3:
+ return
+ else:
+ <do_something(i)>
+ loop123(i+1) # tail call
+
+ loop123()
+
+Another example: enumerate
+------------------------------------
+
+Here is an example of a for loop used to build a data structure::
+
+ def enumerate(values, i=0, acc=()):
+ if i >= len(values):
+ return acc
+ else:
+ return enumerate(
+ values, i+1, acc + ((i, values[i]),))
+
+The trick is to use an (immutable) accumulator
+
+The importance of tail calls
+------------------------------------------------
+
+- in a truly functional language all for-loops are implemented as
+ recursive functions in tail call form
+
+.. class:: incremental
+
+- the compiler is able to recognize them and avoids creating
+ a new stack per each iteration (TCO): no recursion limit
+- for the programmer POV the loop variable is never reassigned
+- it seems *perverse* but it is essential
+- expecially for things like pattern matching
+
+A note on pattern matching
+------------------------------------
+
+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::
+
+ fun fact n = fact' (n, 1)
+ and fact' (0, acc) = acc
+ | fact' (n, acc) = fact' (n-1, acc*n);
+
+In Erlang is used to destructure the messages sent to the Erlang lightweight
+processes.
+
+TCO and debugging
+---------------------------
+
+There has been some heated debate last year due to Guido's dismissal
+of TCO.
+
+.. class:: incremental
+
+ In all fairness I must notice that TCO does not prevent debugging::
+
+ ;; tco.ss
+ (let loop ((x -3))
+ (/ 1 x)
+ (loop (add1 x)))
+
+ (but I agree that iterative is better than recursive)
+
+The pragmatist voice
+---------------------------------
+
+*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.* -- Andrew Kuchling
+
+Example: collecting objects
+------------------------------
+
+::
+
+ 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 < date:
+ storage[client, kind] = mail
+ return storage
+
+For purists at all costs ...
+-----------------------------------------------------
+
+- you can avoid mutation of the storage by introducting a functional
+ update utility::
+
+ def update(d, k, v):
+ newd = d.copy()
+ newd.update({k : v})
+ return newd
+
+... use a helper function
+----------------------------------------
+
+::
+
+ def _collect_mail(storage, mail):
+ # a left-folding function: acc,obj->new-acc
+ client = mail.getclient()
+ kind = mail.getkind()
+ date = mail.getdate()
+ stored = storage.get((client, kind))
+ if stored is None or stored.date < date:
+ return update(
+ storage, (client, kind), mail)
+ else:
+ return storage
+
+... then reduce is your friend
+-------------------------------------
+
+::
+
+ def collect_mail(mails):
+ return reduce(_collect_mail, mails, {})
+
+.. class:: incremental
+
+- except that you should not be *perverse*
+- there is no reason to be functional at any cost if you are using a
+ non-functional language
+- do not fight the language, flow with it
+- and this close the discussion about immutable bindings
+
+2: immutable data
+-------------------------------------------------
+
+- we cannot really get rid of all mutable objects but
+ certainly mutable objects are overused
+
+.. class:: incremental
+
+- mutable objects are often evil
+ (globals, example of nosetests changing my sys.path)
+- mutable objects can be often avoided
+ (functional update may substitute mutation)
+- there are smart functional data structures nowadays
+ (not much in Python)
+- Python has only strings, (named)tuples and frozensets
+
+namedtuple
+--------------------------------------
+
+>>> from collections import namedtuple
+>>> Point = namedtuple('Point', 'x y')
+>>> p1 = Point(0, 0)
+>>> p2 = p1._replace(x=1)
+>>> p2
+(1, 0)
+>>> p1 is p2
+False
+
+(requires copying the full structure in Python). Python also lacks
+immutable dictionaries (say Red/Black trees).
+
+Generators are mutable
+--------------------------------------
+
+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:
+
+ >>> it123 = iter([1, 2, 3])
+ >>> for i in it123: print i,
+ ...
+ 1 2 3
+ >>> for i in it123: print i,
+ ...
+
+The functional way: streams
+-------------------------------------
+
+Looping over a stream does not mutate it::
+
+ > (import (srfi :41 streams))
+ > (define str123 (stream-range 1 4))
+ > (stream-for-each display str123)
+ 123
+ > (stream-for-each display str123)
+ 123
+
+Yet another difference between Python and a true functional language
+
+3: confined side effects?
+-------------------------------------------------
+
+- to be able to distinguish pure functions from
+ impure functions is important::
+
+ @memoize
+ def do_something():
+ result = long_computation()
+ log.info('Computed %s', result)
+ return result
+
+- Haskell is the purest language when it comes to
+ confining side effects
+
+Side effects and unittests
+------------------------------------------
+
+- in Python keeping the distinction between pure and impure functions is a
+ question of good coding style
+
+.. class:: incremental
+
+- common sense tells you that you should decouple I/O from the
+ business logic
+- unit testing is arguably the master path to functional design:
+ if you want to test a thing, make it a pure function
+- if it is difficult to test it is not functional
+
+Usual recommendations
+--------------------------------------
+
+All the usual recommendations to make code more testable, such as
+
+.. class:: incremental
+
+- avoid side effects (including the ones at import time)
+- do not use special variables (damned them!)
+- decouple the system i.e. pass objects around
+- write libraries, not frameworks
+- feel guilty!
+
+are recommendations to make code more functional.
+
+Database connections (bad)
+-----------------------------------------
+
+db = DBSession() # singleton
+
+def read(...):
+ db.read_data( ... )
+
+def write(data, ...):
+ db.write_data(data, ...)
+
+if __name__ == '__main__':
+ db.init(dsn)
+
+Database connections (good)
+-----------------------------------------
+
+def read(db, ...):
+ db.read_data( ... )
+
+def write(db, data, ...):
+ db.write_data(data, ...)
+
+if __name__ == '__main__':
+ db = DBSession(dsn)
+
+FP and databases
+----------------------------------------------------------
+
+- operating on a DB looks like the least functional thing you can do
+ (ex. ``importer.import(fileobj, db)``)
+
+.. class:: incremental
+
+- still can be made functional, at the price of *creating the db*
+ (this is how we write the db tests)::
+
+ def import(lines): # this is a pure function!
+ db = create_db()
+ out = importer.import(lines, db)
+ drop_db(db)
+ return out
+
+Functional design and SQL
+----------------------------------------------------------
+
+- SQL makes a good functional language once you remove mutation
+ (UPDATE and DELETE)
+
+.. class:: incremental
+
+- SELECTs are not really different from list comprehensions
+ (think of LINQ);
+- if you can use a view, use it (tell my recent experience making legacy
+ SQL code more functional)
+- even non-premature optimizations are evil :-(
+
+References
+------------------------------------------------
+
+http://www.phyast.pitt.edu/~micheles/scheme/TheAdventuresofaPythonistainSchemeland.pdf
+http://www.haskell.org/
+http://clojure.org/
+http://docs.python.org/howto/functional.html
+http://www.defmacro.org/ramblings/fp.html
+http://www.cs.cmu.edu/~rwh/theses/okasaki.pdf
+http://srfi.schemers.org/srfi-41/srfi-41.html
+http://funcall.blogspot.com/2009/05/you-knew-id-say-something-part-iv.html
diff --git a/pypers/pycon10/tco.py b/pypers/pycon10/tco.py
new file mode 100644
index 0000000..3b7fd34
--- /dev/null
+++ b/pypers/pycon10/tco.py
@@ -0,0 +1,4 @@
+def loop(x=-3):
+ 1/x
+ return loop(x+1)
+loop()
diff --git a/pypers/pycon10/tco.ss b/pypers/pycon10/tco.ss
new file mode 100644
index 0000000..9b7f17a
--- /dev/null
+++ b/pypers/pycon10/tco.ss
@@ -0,0 +1,4 @@
+;; run this with ikarus -d
+(let loop ((x -3))
+ (/ 1 x)
+ (loop (add1 x)))