Programação Funcional
-
Upload
juarez-da-silva-bochi -
Category
Technology
-
view
360 -
download
0
description
Transcript of Programação Funcional
![Page 1: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/1.jpg)
Programação FuncionalFISL 2013
Juarez Bochi
λSunday, July 14, 13
![Page 2: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/2.jpg)
Juarez Bochi
Sunday, July 14, 13
![Page 3: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/3.jpg)
Juarez Bochi
Sunday, July 14, 13
![Page 4: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/4.jpg)
Juarez Bochi
Sunday, July 14, 13
![Page 5: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/5.jpg)
Juarez Bochi
Sunday, July 14, 13
![Page 6: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/6.jpg)
Juarez Bochi
Sunday, July 14, 13
![Page 7: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/7.jpg)
Agenda
• Motivação
• Conceitos
• Exemplos
• Resumo
Sunday, July 14, 13
![Page 8: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/8.jpg)
Motivação
Sunday, July 14, 13
![Page 9: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/9.jpg)
Ler um arquivo, listar as palavras mais
comuns em ordem decrescente.
Sunday, July 14, 13
![Page 10: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/10.jpg)
Ler um arquivo, listar as palavras mais
comuns em ordem decrescente.
Sunday, July 14, 13
![Page 11: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/11.jpg)
Donald Knuth
X
Sunday, July 14, 13
![Page 12: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/12.jpg)
Donald Knuth Doug McIlroy
X
Sunday, July 14, 13
![Page 13: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/13.jpg)
Donald Knuth Doug McIlroy
X
10+ páginas de Pascal/WEBSunday, July 14, 13
![Page 14: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/14.jpg)
Donald Knuth Doug McIlroy
X
10+ páginas de Pascal/WEB 6 linhas de shellSunday, July 14, 13
![Page 15: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/15.jpg)
tr -cs A-Za-z '\n' |tr A-Z a-z |sort |uniq -c |sort -rn |sed ${1}q
Sunday, July 14, 13
![Page 16: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/16.jpg)
Sunday, July 14, 13
![Page 17: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/17.jpg)
$ cat discurso.txt | tr -cs A-Za-z '\n' | tr A-Z a-z | sort | uniq -c | sort -rn | sed 40q 65 e 48 de 42 a 35 o 32 que 18 os 15 para 15 com 14 mais 13 nao 13 do 11 as 10 um 10 dos 10 da 9 das 8 ela 7 todos 7 se 7 pais 7 muito 6 ruas 6 brasil 5 violencia
Sunday, July 14, 13
![Page 18: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/18.jpg)
“Keep it simple, make it general, and make it intelligible.” Doug McIlroy
Sunday, July 14, 13
![Page 19: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/19.jpg)
“Keep it simple, make it general, and make it intelligible.” Doug McIlroy
Sunday, July 14, 13
![Page 20: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/20.jpg)
Conceitos
Sunday, July 14, 13
![Page 21: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/21.jpg)
Paradigmas
• Imperativo
• Lógico
• Funcional
• Orientado a Objetos
Sunday, July 14, 13
![Page 22: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/22.jpg)
Paradigma Imperativo
Linguagem Computador
Variáveis Mutáveis Endereço de memória
Estruturas de controle (if-then-else, loop)
Jumps
Sunday, July 14, 13
![Page 23: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/23.jpg)
“Can Programming Be Liberated from the von. Neumann Style?”John Backus - Turing Award Lecture
Sunday, July 14, 13
![Page 24: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/24.jpg)
Programação Funcional
• Concentrar em teorias, não mutações
• Minimizar mudança de estados
• Sem estruturas de controle imperativas
• Foco em funções
Sunday, July 14, 13
![Page 25: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/25.jpg)
“Programação Funcional é ortogonal à Orientação
a Objetos”
Sunday, July 14, 13
![Page 26: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/26.jpg)
Elementos de Programação
• Expressões Primitivas
• Meios de Combinação
• Meios de Abstração
Sunday, July 14, 13
![Page 27: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/27.jpg)
Exemplos
Sunday, July 14, 13
![Page 28: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/28.jpg)
First Class Functions
Sunday, July 14, 13
![Page 29: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/29.jpg)
First Class Functions
Sunday, July 14, 13
![Page 30: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/30.jpg)
Closure> var inc, dec;undefined> function contador() {... var x = 0;... inc = function() { return ++x; };... dec = function() { return --x; };... }undefined> contador();undefined
Sunday, July 14, 13
![Page 31: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/31.jpg)
Closure> inc();1> inc();2> dec();1> dec();0> inc();1> xReferenceError: x is not defined
Sunday, July 14, 13
![Page 32: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/32.jpg)
> import Control.Applicative> let foo = fmap (+3) (+2)> foo 1015
Sunday, July 14, 13
![Page 33: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/33.jpg)
> import Control.Applicative> let foo = fmap (+3) (+2)> foo 1015
Sunday, July 14, 13
![Page 34: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/34.jpg)
> (defn soma3 [x] (+ x 3))
Sunday, July 14, 13
![Page 35: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/35.jpg)
> (defn soma3 [x] (+ x 3))
> (map soma3 [2 4 6])(5 7 9)
Sunday, July 14, 13
![Page 36: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/36.jpg)
> (defn soma3 [x] (+ x 3))
> (map soma3 [2 4 6])(5 7 9)
Sunday, July 14, 13
![Page 37: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/37.jpg)
> (defn soma3 [x] (+ x 3))
> (map soma3 [2 4 6])(5 7 9)
> (pmap soma3 [2 4 6])(5 7 9)
Sunday, July 14, 13
![Page 38: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/38.jpg)
Higher Order Functionpessoas = [{'nome': 'Adolfo', 'estado': 'MG'}, {'nome': 'Pedro', 'estado': 'RS'}, {'nome': 'Maria', 'estado': 'AC'}]
def por_estado(pessoa1, pessoa2): return cmp(pessoa1['estado'], pessoa2['estado'])
>>> pprint.pprint(sorted(pessoas, cmp=por_estado))[{'estado': 'AC', 'nome': 'Maria'}, {'estado': 'MG', 'nome': 'Adolfo'}, {'estado': 'RS', 'nome': 'Pedro'}]
Sunday, July 14, 13
![Page 39: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/39.jpg)
Recursão
Sunday, July 14, 13
![Page 40: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/40.jpg)
Recursão
(define (fib n) .. (if (< n 2) .. n .. (+ (fib (- n 1)) (fib (- n 2))))) (fib 10)=> 55
Sunday, July 14, 13
![Page 41: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/41.jpg)
Tail Call Optimization1. fib(5)2. fib(4) + fib(3)3. (fib(3) + fib(2)) + (fib(2) + fib(1))4. ((fib(2) + fib(1)) + (fib(1) + fib(0))) + ((fibb(1) + fib(0)) + fib(1))5. (((fib(1) + fib(0)) + fib(1)) + (fib(1) + fib(0))) + ((fib(1) + fib(0)) +
fib(1))
Sunday, July 14, 13
![Page 42: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/42.jpg)
Tail Call Optimization
(define (fib n) .. (letrec ((fib-aux (lambda (n a b) .. (if (= n 0) .. a .. (fib-aux (- n 1) b (+ a b)))))) .. (fib-aux n 0 1))) (fib 1000)=> 4.346655768693743e+208
1. fib(5)2. fib(4) + fib(3)3. (fib(3) + fib(2)) + (fib(2) + fib(1))4. ((fib(2) + fib(1)) + (fib(1) + fib(0))) + ((fibb(1) + fib(0)) + fib(1))5. (((fib(1) + fib(0)) + fib(1)) + (fib(1) + fib(0))) + ((fib(1) + fib(0)) +
fib(1))
Sunday, July 14, 13
![Page 43: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/43.jpg)
Sunday, July 14, 13
![Page 44: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/44.jpg)
Currying & Partialsdef to_tag(tag, texto): return "<{tag}>{texto}</{tag}>".format(tag=tag, texto=texto)
Sunday, July 14, 13
![Page 45: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/45.jpg)
Currying & Partials
def partial(funcao, argumento): def fn(arg): return funcao(argumento, arg) return fn
def to_tag(tag, texto): return "<{tag}>{texto}</{tag}>".format(tag=tag, texto=texto)
Sunday, July 14, 13
![Page 46: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/46.jpg)
Currying & Partials
def partial(funcao, argumento): def fn(arg): return funcao(argumento, arg) return fn
def to_tag(tag, texto): return "<{tag}>{texto}</{tag}>".format(tag=tag, texto=texto)
negrito = partial(to_tag, 'b')italico = partial(to_tag, 'i')
Sunday, July 14, 13
![Page 47: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/47.jpg)
Currying & Partials
def partial(funcao, argumento): def fn(arg): return funcao(argumento, arg) return fn
def to_tag(tag, texto): return "<{tag}>{texto}</{tag}>".format(tag=tag, texto=texto)
negrito = partial(to_tag, 'b')italico = partial(to_tag, 'i')>>> negrito(italico("Oi, FISL!"))"<b><i>Oi FISL!</i></b>"
Sunday, July 14, 13
![Page 48: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/48.jpg)
Currying & Partials
def partial(funcao, argumento): def fn(arg): return funcao(argumento, arg) return fn
def to_tag(tag, texto): return "<{tag}>{texto}</{tag}>".format(tag=tag, texto=texto)
DSL!!negrito = partial(to_tag, 'b')italico = partial(to_tag, 'i')>>> negrito(italico("Oi, FISL!"))"<b><i>Oi FISL!</i></b>"
Sunday, July 14, 13
![Page 49: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/49.jpg)
Laziness
Sunday, July 14, 13
![Page 50: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/50.jpg)
Laziness
Sunday, July 14, 13
![Page 51: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/51.jpg)
Lazinessdef from(n: Int): Stream[Int] = n #:: from(n+1)
Sunday, July 14, 13
![Page 52: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/52.jpg)
Lazinessdef from(n: Int): Stream[Int] = n #:: from(n+1)
Sunday, July 14, 13
![Page 53: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/53.jpg)
Lazinessdef from(n: Int): Stream[Int] = n #:: from(n+1) val nats = from(0)
Sunday, July 14, 13
![Page 54: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/54.jpg)
Lazinessdef from(n: Int): Stream[Int] = n #:: from(n+1) val nats = from(0)
Sunday, July 14, 13
![Page 55: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/55.jpg)
Lazinessdef from(n: Int): Stream[Int] = n #:: from(n+1) val nats = from(0) def sieve(s: Stream[Int]): Stream[Int] =
Sunday, July 14, 13
![Page 56: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/56.jpg)
Lazinessdef from(n: Int): Stream[Int] = n #:: from(n+1) val nats = from(0) def sieve(s: Stream[Int]): Stream[Int] = s.head #:: sieve(s.tail filter (_ % s.head != 0))
Sunday, July 14, 13
![Page 57: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/57.jpg)
Lazinessdef from(n: Int): Stream[Int] = n #:: from(n+1) val nats = from(0) def sieve(s: Stream[Int]): Stream[Int] = s.head #:: sieve(s.tail filter (_ % s.head != 0))
Sunday, July 14, 13
![Page 58: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/58.jpg)
Lazinessdef from(n: Int): Stream[Int] = n #:: from(n+1) val nats = from(0) def sieve(s: Stream[Int]): Stream[Int] = s.head #:: sieve(s.tail filter (_ % s.head != 0)) val primes = sieve(from(2))
Sunday, July 14, 13
![Page 59: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/59.jpg)
Lazinessdef from(n: Int): Stream[Int] = n #:: from(n+1) val nats = from(0) def sieve(s: Stream[Int]): Stream[Int] = s.head #:: sieve(s.tail filter (_ % s.head != 0)) val primes = sieve(from(2))
Sunday, July 14, 13
![Page 60: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/60.jpg)
Lazinessdef from(n: Int): Stream[Int] = n #:: from(n+1) val nats = from(0) def sieve(s: Stream[Int]): Stream[Int] = s.head #:: sieve(s.tail filter (_ % s.head != 0)) val primes = sieve(from(2)) (primes take N).toList
Sunday, July 14, 13
![Page 61: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/61.jpg)
Data Abstractionclass Zero(Natural): def __init__(self): pass
def __repr__(self): return "0"
def __add__(self, other): return other
Sunday, July 14, 13
![Page 62: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/62.jpg)
Data Abstractionclass Zero(Natural): def __init__(self): pass
def __repr__(self): return "0"
def __add__(self, other): return other
class Natural(object): def __init__(self, anterior): self.anterior = anterior
def __repr__(self): return repr(self.anterior) + " + 1"
def __add__(self, other): return self.anterior + other.sucessor()
def sucessor(self): return Natural(anterior=self)
Sunday, July 14, 13
![Page 63: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/63.jpg)
Data Abstractionclass Zero(Natural): def __init__(self): pass
def __repr__(self): return "0"
def __add__(self, other): return other
class Natural(object): def __init__(self, anterior): self.anterior = anterior
def __repr__(self): return repr(self.anterior) + " + 1"
def __add__(self, other): return self.anterior + other.sucessor()
def sucessor(self): return Natural(anterior=self)>>> zero = Zero()
>>> um = zero.sucessor()>>> dois = um.sucessor()>>> um0 + 1>>> dois0 + 1 + 1>>> um + dois0 + 1 + 1 + 1
Sunday, July 14, 13
![Page 64: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/64.jpg)
Resumo
Sunday, July 14, 13
![Page 65: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/65.jpg)
Blub Paradox
Sunday, July 14, 13
![Page 66: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/66.jpg)
Resumo
Código fácil de entender
Sunday, July 14, 13
![Page 67: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/67.jpg)
Resumo
Código fácil de manter
Sunday, July 14, 13
![Page 68: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/68.jpg)
Resumo
Código fácil de testar
Sunday, July 14, 13
![Page 69: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/69.jpg)
Resumo
Código fácil de escalar
Sunday, July 14, 13
![Page 70: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/70.jpg)
Obrigado!@jbochi
Sunday, July 14, 13
![Page 71: Programação Funcional](https://reader033.fdocument.pub/reader033/viewer/2022042715/559ebc1a1a28ab902a8b469d/html5/thumbnails/71.jpg)
Referências• http://www.leancrew.com/all-this/2011/12/more-shell-less-egg/
• http://onesixtythree.com/literate/literate2.pdf
• http://mitpress.mit.edu/sicp/
• http://www.paulgraham.com/avg.html
• https://www.coursera.org/course/progfun
• http://www.slideshare.net/jbochi/programao-funcional-em-python
• https://raw.github.com/richhickey/slides/master/simplicitymatters.pdf
• http://pragprog.com/magazines/2013-01/functional-programming-basics
• http://adit.io/posts/2013-04-17-functors,_applicatives,_and_monads_in_pictures.html
• http://en.literateprograms.org/Fibonacci_numbers_(Scheme)
• http://norvig.com/21-days.html
• http://www.youtube.com/watch?v=3jg1AheF4n0
• http://www.flickr.com/photos/niceric/74977685/sizes/l/in/
Sunday, July 14, 13