Introdução à Programação Funcional (com Ruby!)
marcelocamargo@linuxmail.org
github.com/haskellcamargo
About.me
- Systems analyst;
- Translator (PT/EN/ES/FR);
- PL researcher;
- Developer of Quack and Capybara programming languages.
TOC
× What in the world is FP?
× FP matters!
× FP concepts in Ruby
Functional Programming is
fun _ → b
What in
the World
is FP?
Paradigma de programação antigo
... mas muito alinhado ao presente
Everything
is a
function
No início, tudo era muito lento...
Ao projetar uma linguagem...
Iniciar na arquitetura de von Neumann* e adicionar abstração...
... Iniciar com bases matemáticas e remover
abstração
* programas e dados contidos no mesmo espaço de memória
OU
Computadores não eram suficientemente poderosos para lidar com tamanha abstração...
LISP era lento e incapaz de atender às demandas da época
Então, dominou a programação imperativa...
MAS
ISSO
MUDOU!
E FP GANHOU
UMA SEGUNDA
CHANCE!
Mas qual a diferença?
Não especifique como deve ser feito.
Especifique o que deve ser feito!
Vamos mergulhar nos conceitos básicos!
Usando Ruby!
FP
concepts
in Ruby
Conceitos básicos
Funções de primeira classe
Funções de mais alta ordem
Closures
Funções puras e determinísticas
Funções de primeira classe
Transparência referencial
Conceitos básicos
Imutabilidade
Pattern matching
Recursividade
Composição de funções
Não se assuste com os nomes!
Funções de primeira classe
add = lambda { |a, b| a + b }
puts add[10, 20]
Métodos, procedimentos e lambdas armazenados em variáveis
Funções de mais alta ordem
(1 .. 10)
.map { |x| x * 3 }
.select { |x| x % 2 == 0 }
.reduce { |acc, x| acc + x }
Passe funções como parâmetros e retorne outras funções
Closures
def add(a, b)
a + b
end
add_10 = method(:add).curry[10]
puts add_10[20]
Acesse e preserve o escopo de execução anterior
Closures
def add(a)
lambda { |b| a + b }
end
add_10 = add 10
puts add_10[20]
Acesse e preserve o escopo de execução anterior
Funções puras e determinísticas
def double_me(n)
n[0] = n[0] * 2
end
val = [20]
double_me val
puts val[0]
f(x) = y. Sem efeitos colaterais. Se entra x agora e sai y, sempre sairá y quando entrar x. Exemplo impuro:
Funções puras e determinísticas
def double_me(n)
n * 2
end
puts double_me 20
f(x) = y. Sem efeitos colaterais. Se entra x agora e sai y, sempre sairá y quando entrar x. Exemplo puro:
Transparência referencial
a = Math.sin 70
b = 80 - 30
puts a * b
puts (Math.sin 70) * (80 - 30)
Equivalência na substituição
Imutabilidade
example = "wow such example"
example.upcase!
puts example
"Variáveis" não variáveis! Devem servir como aliases.
ERRADO:
Imutabilidade
example = "wow such example"
result = example.upcase
puts result
"Variáveis" não variáveis! Devem servir como aliases. O estado deve trafegar, não ser alterado!
CORRETO:
Pattern matching
require 'pattern-match'
using PatternMatch
def fact(n)
match (n) do
with(0) { 1 }
with(n) { n * fact(n - 1) }
end
end
Defina o fluxo do programa através da forma dos seus valores
https://github.com/k-tsj/pattern-match
Recursividade
def fib(n)
if (0..1).include? n
then n
else fib(n - 1) + fib(n - 2) if n > 1
end
end
puts fib 20
Esqueça os loops. Esqueça estruturas imperativas
Composição de funções
class Proc
def self.compose(f, g)
lambda { |*args| f[g[*args]] }
end
def *(g)
Proc.compose(self, g)
end
end
Combine funções e obtenha novas funções.
Vamos implementar composição na linguagem...
Composição de funções
inc = lambda { |x| x + 1 }
double = lambda { |x| x * 2 }
double_inc = double * inc
# (20 + 1) * 2 = 42
puts double_inc[20]
Combine funções e obtenha novas funções.
Vamos utilizar nossa implementação!
map
filter
reduce
map
Aplique uma função a cada elemento da lista e retorne uma nova lista
my_list = 1 .. 10
my_list_by_three = my_list.map do |x|
x * 3
end
filter/select
Aplique uma função a cada elemento da lista e retorne uma nova lista
my_list = 1 .. 10
my_even_list = my_list.select do |x|
x % 2 == 0
end
reduce
Usando um acumulador e x, aplique uma função ao resultado desta com acc e x como parâmetros
my_list = 1 .. 10
my_sum = my_list.reduce do |acc, x|
acc + x
end
((((((((((1 + 2) + 3) + 4) + 5) + 6) + 7) + 8) + 9) + 10
FP
matters
OOP cannot save us anymore
Pelo menos em relação à concorrência e ao paralelismo
1 core ≃ 1k cores
Safer & better code
Escreva código seguro, puro, limpo e melhor
Parallelism
Aproveite o processamento paralelo em múltiplos processadores e núcleos
Testable code
Escreva testes unitários com maior facilidade e garanta que cada parte da aplicação é consistente
Referências & Recomendações
Functional programming should be your #1 priority ─ @jugoncalves
Structure and Interpretation of Computer Programs ─ Sussman, Abelson
How to Design Programs ─ Felleisen, Findler, Flatt, Krishnamurthi
Functional Programming Techniques With Ruby ─ Nathan Kleyn
Tnx!
Questions?
Introdução à Programação Funcional (com Ruby!)
By Marcelo Camargo
Introdução à Programação Funcional (com Ruby!)
- 1,928