Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015
-
Upload
codemotion -
Category
Technology
-
view
974 -
download
3
Transcript of Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015
![Page 1: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/1.jpg)
ROME 27-28 march 2015
functional programming
you already know
@KevlinHenney
![Page 2: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/2.jpg)
![Page 3: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/3.jpg)
![Page 4: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/4.jpg)
![Page 5: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/5.jpg)
![Page 6: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/6.jpg)
functional
programming
higher-order functions
recursion
statelessness
first-class functions
immutability
pure functions
unification
declarative
pattern matching
non-strict evaluation
idempotence
lists
mathematics
lambdas currying
monads
![Page 7: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/7.jpg)
Excel is the world's most popular functional language.
Simon Peyton Jones
![Page 8: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/8.jpg)
To iterate is human,
to recurse divine.
L Peter Deutsch
![Page 9: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/9.jpg)
int factorial(int n)
{
int result = 1;
while(n > 1)
result *= n--;
return result;
}
![Page 10: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/10.jpg)
int factorial(int n)
{
if(n > 1)
return n * factorial(n - 1);
else
return 1;
}
![Page 11: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/11.jpg)
int factorial(int n)
{
return
n > 1
? n * factorial(n - 1)
: 1;
}
![Page 12: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/12.jpg)
n! = 1
(n – 1)! n
if n = 0,
if n > 0. {
![Page 13: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/13.jpg)
n! =
n
k = 1
k
![Page 14: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/14.jpg)
seriesProduct(k, k, 1, n)
![Page 15: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/15.jpg)
reduce(
int.__mul__,
range(1, n+1), 1)
![Page 16: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/16.jpg)
reduce(
lambda l, r: l*r,
range(1, n+1), 1)
![Page 17: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/17.jpg)
![Page 18: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/18.jpg)
![Page 19: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/19.jpg)
![Page 20: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/20.jpg)
#include <stdio.h>
/* printd: print n in decimal */
void printd(int n)
{
if (n < 0) {
putchar('-');
n = -n;
}
if (n / 10)
printd(n / 10);
putchar(n % 10 + '0');
}
![Page 21: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/21.jpg)
![Page 22: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/22.jpg)
/* grep: search for regexp in file */
int grep(char *regexp, FILE *f, char *name)
{
int n, nmatch;
char buf[BUFSIZ];
nmatch = 0;
while (fgets(buf, sizeof buf, f) != NULL) {
n = strlen(buf);
if (n > 0 && buf[n-1] == '\n')
buf[n-1] = '\0';
if (match(regexp, buf)) {
nmatch++;
if (name != NULL)
printf("%s:", name);
printf("%s\n", buf);
}
}
return nmatch;
}
/* matchhere: search for regexp at beginning of text */
int matchhere(char *regexp, char *text)
{
if (regexp[0] == '\0')
return 1;
if (regexp[1] == '*')
return matchstar(regexp[0], regexp+2, text);
if (regexp[0] == '$' && regexp[1] == '\0')
return *text == '\0';
if (*text!='\0' && (regexp[0]=='.' || regexp[0]==*text))
return matchhere(regexp+1, text+1);
return 0;
}
/* match: search for regexp anywhere in text */
int match(char *regexp, char *text)
{
if (regexp[0] == '^')
return matchhere(regexp+1, text);
do { /* must look even if string is empty */
if (matchhere(regexp, text))
return 1;
} while (*text++ != '\0');
return 0;
}
/* matchstar: search for c*regexp at beginning of text */
int matchstar(int c, char *regexp, char *text)
{
do { /* a * matches zero or more instances */
if (matchhere(regexp, text))
return 1;
} while (*text != '\0' && (*text++ == c || c == '.'));
return 0;
}
![Page 23: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/23.jpg)
int atexit(void (*func)(void));
![Page 24: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/24.jpg)
void qsort(
void *base,
size_t nmemb, size_t size,
int (*compar)(
const void *, const void *));
![Page 25: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/25.jpg)
void (*signal(
int sig, void (*func)(int)))(int);
![Page 26: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/26.jpg)
Use procedure arguments to provide
flexibility in an interface.
This technique can greatly simplify
an interface, eliminating a jumble of
parameters that amount to a small
programming language.
Butler W Lampson
"Hints for Computer System Design"
![Page 27: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/27.jpg)
public class HeatingSystem
{
public void turnOn()
public void turnOff()
}
public class Timer
{
public Timer(TimeOfDay toExpire, Runnable toDo)
public void run()
public void cancel()
}
![Page 28: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/28.jpg)
Timer on =
new Timer(
timeToTurnOn,
new Runnable()
{
public void run()
{
heatingSystem.turnOn();
}
});
Timer off =
new Timer(
timeToTurnOff,
new Runnable()
{
public void run()
{
heatingSystem.turnOff();
}
});
![Page 29: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/29.jpg)
class Timer
{
public:
Timer(TimeOfDay toExpire, function<void()> toDo);
void Run();
void Cancel();
...
};
![Page 30: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/30.jpg)
Timer on(
timeOn,
bind(&HeatingSystem::TurnOn, &heatingSystem));
Timer off(
timeOff,
bind(&HeatingSystem::TurnOff, &heatingSystem));
![Page 31: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/31.jpg)
public class Timer
{
public Timer(TimeOfDay toExpire, Action toDo) ...
public void Run() ...
public void Cancel() ...
...
}
![Page 32: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/32.jpg)
Timer on = new Timer(timeOn, heatingSystem.TurnOn);
Timer off = new Timer(timeOff, heatingSystem.TurnOff);
![Page 33: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/33.jpg)
Timer on = new Timer(timeOn, heatingSystem::turnOn);
Timer off = new Timer(timeOff, heatingSystem::turnOff);
![Page 34: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/34.jpg)
Timer on =
new Timer(timeOn, () => heatingSystem.TurnOn());
Timer off =
new Timer(timeOff, () => heatingSystem.TurnOff());
![Page 35: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/35.jpg)
Timer on =
new Timer(timeOn, () -> heatingSystem.turnOn());
Timer off =
new Timer(timeOff, () -> heatingSystem.turnOff());
![Page 36: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/36.jpg)
Timer on(
timeOn, [&]() { heatingSystem.TurnOn(); });
Timer off(
timeOff, [&]() { heatingSystem.TurnOff(); });
![Page 37: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/37.jpg)
William Cook, "On Understanding Data Abstraction, Revisited"
![Page 38: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/38.jpg)
newStack = (let items = ref()
{ isEmpty = #items = 0,
depth = #items,
push = x items := xˆitems,
top = items0
})
![Page 39: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/39.jpg)
var newStack = function() {
var items = []
return {
isEmpty: function() {
return items.length === 0
},
depth: function() {
return items.length
},
push: function(newTop) {
items = items.unshift(newTop)
},
top: function() {
return items[0]
}
}
}
![Page 40: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/40.jpg)
![Page 41: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/41.jpg)
One of the most powerful mechanisms
for program structuring [...] is the block
and procedure concept.
A procedure which is capable of giving
rise to block instances which survive its
call will be known as a class; and the
instances will be known as objects of
that class.
A call of a class generates a new object
of that class.
Ole-Johan Dahl and C A R Hoare
"Hierarchical Program Structures"
![Page 42: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/42.jpg)
Concatenative programming is so called because it uses function composition instead of function application—a non-concatenative language is thus called applicative.
Jon Purdy http://evincarofautumn.blogspot.in/2012/02/
why-concatenative-programming-matters.html
![Page 43: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/43.jpg)
f(g(h(x)))
![Page 44: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/44.jpg)
(f ○ g ○ h)(x)
![Page 45: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/45.jpg)
x h g f
![Page 46: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/46.jpg)
h | g | f
![Page 47: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/47.jpg)
This is the basic reason Unix pipes are so powerful: they form a rudimentary string-based concatenative programming language.
Jon Purdy http://evincarofautumn.blogspot.in/2012/02/
why-concatenative-programming-matters.html
![Page 48: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/48.jpg)
![Page 49: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/49.jpg)
find . -name "*.java" | sed 's/.*\///' | sort | uniq -c | grep -v "^ *1 " | sort -r
Heinz Kabutz "Know Your IDE"
97 Things Every Programmer Should Know
![Page 50: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/50.jpg)
Concurrency
![Page 51: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/51.jpg)
Concurrency
Threads
![Page 52: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/52.jpg)
Concurrency
Threads
Locks
![Page 53: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/53.jpg)
Some people, when confronted with a problem, think, "I know, I'll use threads," and then two they hav erpoblesms.
Ned Batchelder https://twitter.com/#!/nedbat/status/194873829825327104
![Page 54: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/54.jpg)
public class Date implements ... { ... public int getYear() ... public int getMonth() ... public int getDayInMonth() ... public void setYear(int newYear) ... public void setMonth(int newMonth) ... public void setDayInMonth(int newDayInMonth) ... ... }
![Page 55: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/55.jpg)
public class Date implements ... { ... public int getYear() ... public int getMonth() ... public int getWeekInYear() ... public int getDayInYear() ... public int getDayInMonth() ... public int getDayInWeek() ... public void setYear(int newYear) ... public void setMonth(int newMonth) ... public void setWeekInYear(int newWeek) ... public void setDayInYear(int newDayInYear) ... public void setDayInMonth(int newDayInMonth) ... public void setDayInWeek(int newDayInWeek) ... ... }
![Page 56: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/56.jpg)
public final class Date implements ... { ... public int getYear() ... public int getMonth() ... public int getWeekInYear() ... public int getDayInYear() ... public int getDayInMonth() ... public int getDayInWeek() ... ... }
![Page 57: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/57.jpg)
When it is not necessary to change, it is necessary not to change.
Lucius Cary
![Page 58: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/58.jpg)
public final class Date implements ... { ... public int getYear() ... public int getMonth() ... public int getWeekInYear() ... public int getDayInYear() ... public int getDayInMonth() ... public int getDayInWeek() ... ... }
![Page 59: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/59.jpg)
public final class Date implements ... { ... public int year() ... public int month() ... public int weekInYear() ... public int dayInYear() ... public int dayInMonth() ... public int dayInWeek() ... ... }
![Page 60: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/60.jpg)
Mutable
Immutable
Unshared Shared
Unshared mutable data needs no synchronisation
Unshared immutable data needs no synchronisation
Shared mutable data needs synchronisation
Shared immutable data needs no synchronisation
![Page 61: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/61.jpg)
![Page 62: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/62.jpg)
Instead of using threads and shared memory
as our programming model, we can use
processes and message passing. Process here
just means a protected independent state
with executing code, not necessarily an
operating system process.
Russel Winder "Message Passing Leads to Better Scalability in Parallel Systems"
![Page 63: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/63.jpg)
OOP to me means only messaging, local retention and protection and hiding of state-process, and extreme late-binding of all things. It can be done in Smalltalk and in LISP. There are possibly other systems in which this is possible, but I'm not aware of them.
Alan Kay
![Page 64: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/64.jpg)
Languages such as Erlang (and occam before
it) have shown that processes are a very
successful mechanism for programming
concurrent and parallel systems. Such
systems do not have all the synchronization
stresses that shared-memory, multithreaded
systems have.
Russel Winder "Message Passing Leads to Better Scalability in Parallel Systems"
![Page 65: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/65.jpg)
![Page 66: Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015](https://reader030.fdocuments.us/reader030/viewer/2022032616/55a687d71a28ab3f1e8b4647/html5/thumbnails/66.jpg)
http://xkcd.com/224/
We lost the documentation on quantum mechanics.
You'll have to decode the regexes yourself.