-
-
Save alixedi/e95252d7df0d1090d5b03aaf6ed1389a to your computer and use it in GitHub Desktop.
Anjana Vakil, "Mary had a little lambda", EuroPython 2017: https://ep2017.europython.eu/conference/talks/mary-had-a-little-lambda
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"cells": [ | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "slide" | |
} | |
}, | |
"source": [ | |
"# Mary had a little lambda\n", | |
"\n", | |
"[@AnjanaVakil](https://twitter.com/AnjanaVakil)\n", | |
"\n", | |
"EuroPython 2017\n", | |
"\n", | |
"\n", | |
"A gist of this Jupyter Notebook lives [here](https://gist.github.com/vakila/3d5cebaebf01c4c77b289b9a0388e3c8)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "slide" | |
} | |
}, | |
"source": [ | |
"## Hi! I'm Anjana\n", | |
"\n", | |
"Software engineer at \n", | |
"\n", | |
"*Psst! We're hiring!*\n", | |
"\n", | |
"Alum of \n", | |
"* [The Recurse Center](https://www.recurse.com) programming retreat\n", | |
"* [Outreachy](http://www.outreachy.org) internship program @ [Mozilla](http://www.mozilla.org)\n", | |
"\n", | |
"[Mozilla TechSpeaker](https://wiki.mozilla.org/TechSpeakers)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "slide" | |
} | |
}, | |
"source": [ | |
"### and... poet 😜\n", | |
"\n", | |
"```\n", | |
"Mary had a little lambda, 𝛌🐑\n", | |
"a function pure as snow. ❄️\n", | |
"\n", | |
"For every program that Mary wrote, 💻\n", | |
"the lambda was all she needed to know. 💡\n", | |
"```\n", | |
"\n", | |
"🐏🐑🐏🐑" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "slide" | |
} | |
}, | |
"source": [ | |
"## 𝛌 calculus\n", | |
"\n", | |
"* Mathematical formalism\n", | |
"* Invented by this dude (Alonzo Church) starting 1932:\n", | |
" \n", | |
"* Universal model of computation (Turing-complete) (NBD)\n", | |
"* Untyped or typed\n" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "slide" | |
} | |
}, | |
"source": [ | |
" | ** 𝛌 ** | ** `lambda` **\n", | |
"--- | --- | ---\n", | |
"*used for* | thinking | programming (🐍)\n", | |
"*side effects?* | no way | maybe\n", | |
"*inputs* | 1 | 0+\n", | |
"*outputs* | 1 | 0+\n", | |
"*making one*<br>*(\"abstraction\")*| *λx.x* | `lambda x: x`\n", | |
" | *λx.λy.x+y* | `lambda x, y: x + y`<br>`lambda x: lambda y: x + y`\n", | |
"*using one*<br>*(\"application\")* | *(λx.x+1) 5*<br>*5+1*<br>*6* | `(lambda x: x+1)(5)`*<br>*`5+1`<br>`6`\n" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"source": [ | |
"### If we use `lambda` like 𝛌, **what can we make**?" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"source": [ | |
"WARNING: Experimentation, sillyness, & learning ahead! 😜\n", | |
" \n", | |
"For useful programming tips, please make a U-turn 🖖" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "slide" | |
} | |
}, | |
"source": [ | |
"## Numbers!\n", | |
"\n", | |
"Counting is fun!\n", | |
"\n", | |
"What can we count if all we have are functions?" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"source": [ | |
"We can count **function applications** (calls)!" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 1, | |
"metadata": { | |
"collapsed": true, | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [], | |
"source": [ | |
"zero = lambda f: lambda x: x" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 2, | |
"metadata": { | |
"collapsed": true, | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [], | |
"source": [ | |
"one = lambda f: lambda x: f(x)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 3, | |
"metadata": { | |
"collapsed": true, | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [], | |
"source": [ | |
"two = lambda f: lambda x: f(f(x))" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 4, | |
"metadata": { | |
"collapsed": true, | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [], | |
"source": [ | |
"three = lambda f: lambda x: f(f(f(x)))" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "slide" | |
} | |
}, | |
"source": [ | |
"### Wait... are you sure these are numbers?" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 5, | |
"metadata": { | |
"collapsed": true, | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [], | |
"source": [ | |
"# cheating! but just for sanity checks...\n", | |
"\n", | |
"to_int = lambda n: n(lambda i: i+1)(0)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 6, | |
"metadata": { | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"0" | |
] | |
}, | |
"execution_count": 6, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"# zero = lambda f: lambda x: x\n", | |
"to_int(zero)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 7, | |
"metadata": { | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"1" | |
] | |
}, | |
"execution_count": 7, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"# one = lambda f: lambda x: f(x)\n", | |
"to_int(one)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 8, | |
"metadata": { | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"2" | |
] | |
}, | |
"execution_count": 8, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"# two = lambda f: lambda x: f(f(x))\n", | |
"to_int(two)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 9, | |
"metadata": { | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"3" | |
] | |
}, | |
"execution_count": 9, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"# three = lambda f: lambda x: f(f(f(x)))\n", | |
"to_int(three)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "slide" | |
} | |
}, | |
"source": [ | |
"## Higher numbers!\n", | |
"\n", | |
"Successor function: given a number, get the next number" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 10, | |
"metadata": { | |
"collapsed": true, | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [], | |
"source": [ | |
"succ = lambda n: lambda f: lambda x: f(n(f)(x))" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 11, | |
"metadata": { | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"4" | |
] | |
}, | |
"execution_count": 11, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"four = succ(three)\n", | |
"to_int(four)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 12, | |
"metadata": { | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"5" | |
] | |
}, | |
"execution_count": 12, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"five = succ(four)\n", | |
"to_int(five)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 13, | |
"metadata": { | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"7" | |
] | |
}, | |
"execution_count": 13, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"seven = succ(succ(succ(four)))\n", | |
"to_int(seven)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 14, | |
"metadata": { | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"8" | |
] | |
}, | |
"execution_count": 14, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"eight = seven(succ)(one)\n", | |
"to_int(eight)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "slide" | |
} | |
}, | |
"source": [ | |
"Yay! We have numbers! \n", | |
"\n", | |
"aka...\n", | |
"\n", | |
"### Church Numerals" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "slide" | |
} | |
}, | |
"source": [ | |
"## Arithmetic!\n", | |
"\n", | |
"How can we add two numbers `n` and `m`, when numbers are loop-counters?" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"source": [ | |
"Loop `n` times, then loop `m` more times!" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 15, | |
"metadata": { | |
"collapsed": true, | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [], | |
"source": [ | |
"add = lambda n: lambda m: lambda f: lambda x: m(f)(n(f)(x))" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 16, | |
"metadata": { | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"10" | |
] | |
}, | |
"execution_count": 16, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"ten = add(eight)(two)\n", | |
"to_int(ten)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 17, | |
"metadata": { | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"11" | |
] | |
}, | |
"execution_count": 17, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"to_int(add(three)(eight))" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "slide" | |
} | |
}, | |
"source": [ | |
"## Arithmetic!\n", | |
"\n", | |
"What about multiplying `n` and `m`?" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"source": [ | |
"Loop `n` times, `m` times over!" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 18, | |
"metadata": { | |
"collapsed": true, | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [], | |
"source": [ | |
"mul = lambda n: lambda m: lambda f: lambda x: m(n(f))(x)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 19, | |
"metadata": { | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"6" | |
] | |
}, | |
"execution_count": 19, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"twelve = mul(four)(three)\n", | |
"to_int(mul(three)(two))" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "slide" | |
} | |
}, | |
"source": [ | |
"## Arithmetic!\n", | |
"\n", | |
"What about `n` to the power of `m`?" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 20, | |
"metadata": { | |
"collapsed": true, | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [], | |
"source": [ | |
"power = lambda n: lambda m: m(n)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 21, | |
"metadata": { | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"8" | |
] | |
}, | |
"execution_count": 21, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"to_int(power(two)(three))" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "slide" | |
} | |
}, | |
"source": [ | |
"Me: \"Excuse me Mr. Church...\"" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"source": [ | |
"Alonzo's ghost: \"Yes?\"" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"source": [ | |
"Me: \"What's the answer to life, the universe, and everything?\"" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"source": [ | |
"AG: \"Well...\"" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 22, | |
"metadata": { | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"42" | |
] | |
}, | |
"execution_count": 22, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"answer = add(ten)(power(two)(five))\n", | |
"to_int(answer)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "slide" | |
} | |
}, | |
"source": [ | |
"OK cool, we can do some (simple) math!\n", | |
"\n", | |
"### What else do we need to write programs?" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "slide" | |
} | |
}, | |
"source": [ | |
"## Booleans! Conditionals!\n", | |
"\n", | |
"These go hand-in-hand " | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 23, | |
"metadata": { | |
"collapsed": true, | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [], | |
"source": [ | |
"# if (condition):\n", | |
"# (then do this)\n", | |
"# else:\n", | |
"# (else do this)\n", | |
"\n", | |
"ifthenelse = lambda cond: lambda then_do: lambda else_do: cond(then_do)(else_do)\n", | |
"\n", | |
"troo = lambda then_do: lambda else_do: then_do\n", | |
"falz = lambda then_do: lambda else_do: else_do" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 24, | |
"metadata": { | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"1" | |
] | |
}, | |
"execution_count": 24, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"tired = falz\n", | |
"\n", | |
"coffees_today = ifthenelse(tired)(three)(one)\n", | |
"to_int(coffees_today)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "slide" | |
} | |
}, | |
"source": [ | |
"## Logic!" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 25, | |
"metadata": { | |
"collapsed": true, | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [], | |
"source": [ | |
"# not\n", | |
"opposite = lambda boolean: lambda thn: lambda els: boolean(els)(thn)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 26, | |
"metadata": { | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"True" | |
] | |
}, | |
"execution_count": 26, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"# more cheating, just for simplicity's sake...\n", | |
"to_bool = lambda boolean: boolean(True)(False)\n", | |
"\n", | |
"to_bool(troo)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 27, | |
"metadata": { | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"True" | |
] | |
}, | |
"execution_count": 27, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"to_bool(opposite(falz))" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "slide" | |
} | |
}, | |
"source": [ | |
"## Predicates!" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 28, | |
"metadata": { | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"True" | |
] | |
}, | |
"execution_count": 28, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"is_zero = lambda n: n(lambda _: falz)(troo)\n", | |
"\n", | |
"to_bool(is_zero(zero))" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 29, | |
"metadata": { | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"True" | |
] | |
}, | |
"execution_count": 29, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"is_even = lambda n: n(opposite)(troo)\n", | |
"\n", | |
"to_bool(is_even(zero))" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "slide" | |
} | |
}, | |
"source": [ | |
"## More logic!" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 30, | |
"metadata": { | |
"collapsed": true, | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [], | |
"source": [ | |
"# and\n", | |
"both = lambda boola: lambda boolb: boola(boolb)(boola)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 31, | |
"metadata": { | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"False" | |
] | |
}, | |
"execution_count": 31, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"to_bool(both(falz)(troo))" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 32, | |
"metadata": { | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"False" | |
] | |
}, | |
"execution_count": 32, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"to_bool(both(troo)(falz))" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 33, | |
"metadata": { | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"False" | |
] | |
}, | |
"execution_count": 33, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"to_bool(both(falz)(troo))" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 34, | |
"metadata": { | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"False" | |
] | |
}, | |
"execution_count": 34, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"to_bool(both(falz)(falz))" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "slide" | |
} | |
}, | |
"source": [ | |
"## More logic!" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 35, | |
"metadata": { | |
"collapsed": true, | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [], | |
"source": [ | |
"# or\n", | |
"inc_or = lambda boola: lambda boolb: boola(boola)(boolb)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 36, | |
"metadata": { | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"True" | |
] | |
}, | |
"execution_count": 36, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"to_bool(inc_or(falz)(troo))" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 37, | |
"metadata": { | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"True" | |
] | |
}, | |
"execution_count": 37, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"to_bool(inc_or(troo)(falz))" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 38, | |
"metadata": { | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"True" | |
] | |
}, | |
"execution_count": 38, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"to_bool(inc_or(falz)(troo))" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 39, | |
"metadata": { | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"False" | |
] | |
}, | |
"execution_count": 39, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"to_bool(inc_or(falz)(falz))" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "slide" | |
} | |
}, | |
"source": [ | |
"Cool, we've got some data!\n", | |
"\n", | |
"### What about data **structures**?" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "slide" | |
} | |
}, | |
"source": [ | |
"## Lists!\n", | |
"\n", | |
"What can a list contain?" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"source": [ | |
"* Nothing (empty, aka `nil`)\n", | |
"* One thing\n", | |
"* Multiple things" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"source": [ | |
"We'll build lists out of pairs of two things" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 40, | |
"metadata": { | |
"slideshow": { | |
"slide_type": "slide" | |
} | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"2" | |
] | |
}, | |
"execution_count": 40, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"make_pair = lambda left: lambda right: lambda f: f(left)(right)\n", | |
"\n", | |
"left = lambda pair: pair(troo)\n", | |
"right = lambda pair: pair(falz)\n", | |
"\n", | |
"to_int(right(make_pair(three)(two)))" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 41, | |
"metadata": { | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"True" | |
] | |
}, | |
"execution_count": 41, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"# the empty list\n", | |
"nil = make_pair(troo)(troo)\n", | |
"\n", | |
"# A list will have the form\n", | |
"# (is_empty, (head, tail))\n", | |
"\n", | |
"# only nil will have troo as left element\n", | |
"is_empty = left\n", | |
"\n", | |
"to_bool(is_empty(nil))" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "slide" | |
} | |
}, | |
"source": [ | |
"## Lists!" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 42, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [ | |
"# to add something to a list, we prepend the item to the list\n", | |
"# e.g. new_list = (is_empty=falz, (item, old_list))\n", | |
"prepend = lambda item: lambda l: make_pair(falz)(make_pair(item)(l))\n", | |
"\n", | |
"# to get the head (first item in the list) and tail (rest of the list) of non-empty list\n", | |
"# we have to unpack the right part of the pair\n", | |
"# remember non-empty list form: (is_empty, (head, tail))\n", | |
"head = lambda l: left(right(l))\n", | |
"tail = lambda l: right(right(l))" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 43, | |
"metadata": { | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"1" | |
] | |
}, | |
"execution_count": 43, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"coffees_day_1 = prepend(two)(nil) # (2,nil)\n", | |
"coffees_per_day = prepend(three)(prepend(one)(coffees_day_1)) # (3,(1,(2,nil)))\n", | |
"\n", | |
"to_int(head(tail(coffees_per_day)))" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "slide" | |
} | |
}, | |
"source": [ | |
"Yay, look at all the stuff we've got!\n", | |
"\n", | |
"* Data\n", | |
" * (natural) numbers\n", | |
" * booleans\n", | |
" * lists\n", | |
"* Arithmetic\n", | |
"* Logic & Control flow\n", | |
"\n", | |
"Representing data this way is called...\n", | |
"\n", | |
"### Church Encoding" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "slide" | |
} | |
}, | |
"source": [ | |
"### There's so much more we could do!\n", | |
"\n", | |
"* Predecessor, subtract, divide\n", | |
"* (In)equality\n", | |
"* Strings (as lists of characters represented by their ASCII codes)\n", | |
"* List manipulations (e.g. map, reduce, filter)\n", | |
"* ...y'know, all of computation" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "slide" | |
} | |
}, | |
"source": [ | |
"### Even OBJECTS!\n", | |
"\n", | |
"... wait, what?" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"source": [ | |
"Alan Kay, founding father of OOP, said ([Message to Smalltalk/Squeak mailing list, 1998](http://wiki.c2.com/?AlanKayOnMessaging)):\n", | |
"> I'm sorry that I long ago coined the term \"objects\" for this topic because it gets many people to focus on the lesser idea. The big idea is \"messaging\".\n", | |
"\n" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "slide" | |
} | |
}, | |
"source": [ | |
"### FP & OOP: BFFs" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "-" | |
} | |
}, | |
"source": [ | |
"*Object* : thing which receives messages (method name + arguments) and gives responses\n", | |
"\n", | |
"*(Lambda) function* : thing which takes input and returns output\n", | |
"\n", | |
"\n", | |
"Both define data in terms of **behavior**!" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "slide" | |
} | |
}, | |
"source": [ | |
"### FP & OOP: BFFs" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"source": [ | |
"Lambda calculus\n", | |
"\n", | |
"```\n", | |
"TRUE := λx.λy.x\n", | |
"FALSE := λx.λy.y\n", | |
"```" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"source": [ | |
"Smalltalk (iconic OOP language by Kay et al.)\n", | |
"\n", | |
"```\n", | |
"class True\n", | |
" ifTrue: a ifFalse: b\n", | |
" ^ a value\n", | |
"\n", | |
"class False\n", | |
" ifTrue: a ifFalse: b\n", | |
" ^ b value\n", | |
"```" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "slide" | |
} | |
}, | |
"source": [ | |
"This was just a taster...\n", | |
"### Go learn more lambdas! 𝛌🐑\n", | |
"\n", | |
"Check out \"Fun with Lambdas\" by Corey Haines\n", | |
" * [Upcoming book](https://leanpub.com/fun_with_lambdas)\n", | |
" * [Talk at GOTO Chicago 2015](https://youtu.be/QPqoFCHpLF4)\n", | |
"\n", | |
"\n", | |
"#### Here's some other references for you!\n", | |
"* Mary Rose Cook, [\"A practical introduction to functional programming\"](https://maryrosecook.com/blog/post/a-practical-introduction-to-functional-programming), \n", | |
"* William Cook, [“A Proposal for Simplified, Modern Definitions of ‘Object’ and ‘Object Oriented’”](http://wcook.blogspot.fr/2012/07/proposal-for-simplified-modern.html), 2012" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "slide" | |
} | |
}, | |
"source": [ | |
"# 💚Thank you!💚\n", | |
"\n", | |
"### Speaking opportunity courtesy of ÜberResearch and EuroPython\n", | |
"\n", | |
"### Inspiration courtesy of Corey Haines & Darius Bacon\n", | |
"\n", | |
"### Slides courtesy of Damian Avila's [RISE](https://github.com/damianavila/RISE) for Jupyter notebook\n", | |
"\n", | |
"### Lambda calculus courtesy of Alonzo Church \n", | |
"\n", | |
"## I'm [@AnjanaVakil](https://twitter.com/AnjanaVakil)!" | |
] | |
} | |
], | |
"metadata": { | |
"celltoolbar": "Slideshow", | |
"kernelspec": { | |
"display_name": "Python 3", | |
"language": "python", | |
"name": "python3" | |
}, | |
"language_info": { | |
"codemirror_mode": { | |
"name": "ipython", | |
"version": 3 | |
}, | |
"file_extension": ".py", | |
"mimetype": "text/x-python", | |
"name": "python", | |
"nbconvert_exporter": "python", | |
"pygments_lexer": "ipython3", | |
"version": "3.5.2" | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 2 | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment