marcelocamargo@linuxmail.org
github.com/haskellcamargo
× What in the world is FP?
× FP matters!
× FP concepts in Ruby
fun _ → b
* programas e dados contidos no mesmo espaço de memória
OU
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
Imutabilidade
Pattern matching
Recursividade
Composição de funções
add = lambda { |a, b| a + b }
puts add[10, 20]
Métodos, procedimentos e lambdas armazenados em variáveis
(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
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
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
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:
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:
a = Math.sin 70
b = 80 - 30
puts a * b
puts (Math.sin 70) * (80 - 30)
Equivalência na substituição
example = "wow such example"
example.upcase!
puts example
"Variáveis" não variáveis! Devem servir como aliases.
ERRADO:
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:
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
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
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...
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!
my_list = 1 .. 10
my_list_by_three = my_list.map do |x|
x * 3
end
my_list = 1 .. 10
my_even_list = my_list.select do |x|
x % 2 == 0
end
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
Pelo menos em relação à concorrência e ao paralelismo
1 core ≃ 1k cores
Questions?