SlideShare uma empresa Scribd logo
1 de 65
Baixar para ler offline
Programação Funcional
(Para humanos)
Pedro Castilho
20/06/2017
plc@cin.ufpe.br
Pedro Castilho
(Unicórnios são muito importantes
na programação funcional)
• 9˚ período de EC (tecnicamente)
• Viciado em programação funcional
• Lisper desde 2011
• Ex-monitor de PLC
Pedro Castilho
(Morrendo de medo de bater água no notebook)
• Competidor IoT internacional
Pedro Castilho
(Baixem na app store, beijos)
• Competidor IoT internacional
• Desenvolvedor iOS
Pedro Castilho
(Infelizmente não posso dar muitos detalhes)
• Competidor IoT internacional
• Desenvolvedor iOS
• Estagiário (mobile híbrido)
Programação Funcional
(Para humanos)
Programação Funcional
(Pode te ajudar)
Roteiro
• O que é programação funcional?
• Por que programação funcional importa?
• Programando funcionalmente na prática
Roteiro
• O que é programação funcional?
• Por que programação funcional importa?
• Programando funcionalmente na prática
O que a maioria das pessoas espera
1 (defn (assign-cluster pt centres)
2 (let* ((distances (map
3 (lambda (centre) (euclidean-distance centre pt))
4 centres))
5 (smallest (apply min distances)))
6 (list-index (lambda (d) (= d smallest)) distances)))
O que a maioria das pessoas espera
1 kMeansPP :: MonadRandom m => Int -> [Vec] -> m [Cluster]
2 kMeansPP n pts = kMeansIteration pts <$> centroids
3 where centroids = iterate (>>= nextCentroid) x0 !! (n-1)
4 x0 = take 1 <$> randomElements pts
5 nextCentroid cs = (: cs) <$> fromList (map (weight cs) pts)
6 weight cs x = (x, toRational $ distance x (cs `nearestTo` x))
Hoje não vai ser assim.
Você NÃO precisa:
• Ser um “monstro" da programação
• Saber matemática complexa
• Saber uma linguagem funcional
• Ter cursado PLC
• Saber usar Monads
Você PRECISA:
• Saber programar
Problema:
Converter os valores de uma lista/array
1 using System;
2
3 namespace Ex1 {
4 interface IConversor<T, U> {
5 U Converter(T valor);
6 }
7
8 class Programa {
9 static U[] Converter<T, U>(T[] entrada, IConversor<T, U> conversor) {
10 U[] resultado = new U[input.length];
11
12 for (int i = 0; i < input.length; i++) {
13 resultado[i] = conversor.Converter(entrada[i]);
14 }
15
16 return resultado;
17 }
18
19 class ConversorQuadrado: IConversor<int, string> {
20 public string Converter(int i) {
21 return (i * i).toString();
22 }
23 }
24
25 class ConversorEscala: IConversor<int, string> {
26 readonly int Escala;
27
28 public ConversorEscala(int escala) {
29 this.Escala = escala;
30 }
31
32 public string Converter(int i) {
33 return (i * escala).toString();
34 }
35 }
36
37 static void Main(string[] args) {
38 int[] nums = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
39
40 string[] qnums = Converter<int, string>(nums, new ConversorQuadrado());
41 string[] tnums = Converter<int, string>(nums, new ConversorEscala(3));
42 Console.WriteLine(string.Join(", ", qnums));
43 Console.WriteLine(string.Join(", ", tnums));
44 }
45 }
46 }
Agora em um estilo mais funcional:
1 func converter<T, U>(_ entrada: [T], usando conversor: (T) -> U) -> [U] {
2 var resultado: [T] = []
3 for valor in entrada {
4 resultado.append(conversor(valor))
5 }
6 return resultado
7 }
8
9 func conversorQuadrado(_ i: Int) -> String {
10 return String(i * i)
11 }
12
13 func conversorEscala(_ i: Int, escala: Int) -> String {
14 return String(escala * i)
15 }
16
17 let nums = Array<Int>(1...10)
18 let qnums = converter(nums, usando: conversorQuadrado)
19 print(", ".join(qnums))
20 // e a escala?
1 func converter<T, U>(_ entrada: [T], usando conversor: (T) -> U) -> [U] {
2 var resultado: [T] = []
3 for valor in entrada {
4 resultado.append(conversor(valor))
5 }
6 return resultado
7 }
8
9 func conversorQuadrado(_ i: Int) -> String {
10 return String(i * i)
11 }
12
13 func conversorEscala(escala: Int) -> ((Int) -> String) {
14 return { x in x * escala }
15 }
16
17 let nums = Array<Int>(1...10)
18 let qnums = converter(nums, usando: conversorQuadrado)
19 print(", ".join(qnums))
20 let tnums = converter(nums, usando: conversorEscala(3))
Dúvidas?
Funções de Primeira Classe
Funções de Primeira Classe
• Podem ser guardadas em variáveis
• Podem ser passadas como argumentos
• Podem ser retornadas de funções
• Compõem comportamentos complexos
1 func converter<T, U>(_ entrada: [T], usando conversor: (T) -> U) -> [U] {
2 return entrada.map(conversor)
3 }
4
5 func conversorQuadrado(_ i: Int) -> String {
6 return String(i * i)
7 }
8
9 func conversorEscala(escala: Int) -> ((Int) -> String) {
10 return { x in x * escala }
11 }
12
13 let nums = Array<Int>(1...10)
14 let qnums = converter(nums, usando: conversorQuadrado)
15 print(", ".join(qnums))
16 let tnums = converter(nums, usando: conversorEscala(3))
17 print(", ".join(tnums))
Funções de Primeira Classe Fundamentais
• map: Transforma cada elemento de uma lista/array
• filter: Remove elementos de uma lista/array
• reduce: Produz um resultado agregado de uma lista/array
Funções de Primeira Classe Fundamentais
map(f, l)
l =
f =
Funções de Primeira Classe Fundamentais
map(f, l)
l =
f =
Funções de Primeira Classe Fundamentais
map(f, l)
l =
f =
Funções de Primeira Classe Fundamentais
map(f, l)
l =
f =
Funções de Primeira Classe Fundamentais
map(f, l)
resultado =
f =
l =
Funções de Primeira Classe Fundamentais
filter(f, l)
resultado =
f =
l =
?
Funções de Primeira Classe Fundamentais
reduce(f, z, l)
resultado =
f =
l =
z =
Funções de Primeira Classe Fundamentais
reduce(f, z, l)
resultado =
f =
l =
z =
Funções de Primeira Classe Fundamentais
reduce(f, z, l)
resultado =
f =
l =
z =
Funções de Primeira Classe Fundamentais
• Disponíveis em quase qualquer linguagem hoje
• Em C#: Usando LINQ
• Em Java: Usando Streams
• Em Python: Parte da biblioteca padrão
1 using System;
2 using System.Linq;
3
4 namespace Ex1 {
5 class Programa {
6 static U[] Converter<T, U>(T[] input, Func<T, U> conversor) {
7 return input.Select(valor => conversor(valor)).ToArray();
8 }
9
10 static void Main(string[] args) {
11 int[] nums = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
12
13 string[] qnums = Converter<int, string>(nums, x => x * x);
14 string[] tnums = Converter<int, string>(nums, x => 3 * x);
15 Console.WriteLine(string.Join(", ", qnums));
16 Console.WriteLine(string.Join(", ", tnums));
17 }
18 }
19 }
Dúvidas?
Funções Lambda
(ou funções anônimas)
1 let nums = Array<Int>(1...10)
2 let qnums = nums.map({ i in String(i * i) })
3 print(", ".join(qnums))
4 let tnums = nums.map({ i in String(i * 3) })
5 print(", ".join(tnums))
Funções Lambda
(ou funções anônimas)
Sintaxe
Sintaxe
Java:
C#:



JavaScript ES6:
JavaScript ES5:
Python:
Ruby:
Swift:
(argumentos) -> { código }
argumentos => { código }
(argumentos) => { código }
function(argumentos) { código }
lambda argumentos: código
|argumentos| { código }
{ argumentos in código }
Roteiro
• O que é programação funcional?
• Por que programação funcional importa?
• Programando funcionalmente na prática
1 pessoas = [{'nome': 'Pedro', 'altura': 189},
2 {'nome': 'Maíra', 'altura': 173},
3 {'nome': 'Julia', 'altura': 162},
4 {'nome': 'César', 'altura': 186},
5 {'nome': 'Cláudia', 'altura': 162}]
1 pessoas = [{'nome': 'Pedro', 'altura': 189},
2 {'nome': 'Maíra', 'altura': 173},
3 {'nome': 'Julia', 'altura': 162},
4 {'nome': 'César', 'altura': 186},
5 {'nome': 'Cláudia', 'altura': 162}]
Problema:
Imprimir as pessoas com altura acima de 1,80m
1 pessoas = [{'nome': 'Pedro', 'altura': 189},
2 {'nome': 'Maíra', 'altura': 173},
3 {'nome': 'Julia', 'altura': 162},
4 {'nome': 'César', 'altura': 186},
5 {'nome': 'Cláudia', 'altura': 162}]
6
7 limite_altura = 180
8 pessoas_altas = []
9 for pessoa in pessoas:
10 if 'altura' in pessoa and pessoa['altura'] > limite_altura:
11 pessoas_altas.append(pessoa)
12
13 print(pessoas_altas)
1 pessoas = [{'nome': 'Pedro', 'altura': 189},
2 {'nome': 'Maíra', 'altura': 173},
3 {'nome': 'Julia', 'altura': 162},
4 {'nome': 'César', 'altura': 186},
5 {'nome': 'Cláudia', 'altura': 162}]
6
7 limite_altura = 180
8 pessoas_altas = filter(lambda p: 'altura' in p
and p['altura'] > limite_altura,
9 pessoas)
10
11 print(pessoas_altas)
Novo Problema:
Também imprimir a altura média das pessoas com altura acima de 1,80m
1 pessoas = [{'nome': 'Pedro', 'altura': 189},
2 {'nome': 'Maíra', 'altura': 173},
3 {'nome': 'Julia', 'altura': 162},
4 {'nome': 'César', 'altura': 186},
5 {'nome': 'Cláudia', 'altura': 162}]
6
7 limite_altura = 180
8 pessoas_altas = []
9 altura_total = 0
10 for pessoa in pessoas:
11 if 'altura' in pessoa and pessoa['altura'] > limite_altura:
12 pessoas_altas.append(pessoa)
13 altura_total += pessoa['altura']
14
15 print(pessoas_altas)
16 if len(pessoas_altas) > 0:
17 media_altura = altura_total / len(pessoas_altas)
1 pessoas = [{'nome': 'Pedro', 'altura': 189},
2 {'nome': 'Maíra', 'altura': 173},
3 {'nome': 'Julia', 'altura': 162},
4 {'nome': 'César', 'altura': 186},
5 {'nome': 'Cláudia', 'altura': 162}]
6
7 limite_altura = 180
8 pessoas_altas = filter(lambda p: 'altura' in p
and p['altura'] > limite_altura,
9 pessoas)
10
11 num_pessoas_altas = len(pessoas_altas)
12
13 altura_total = reduce(lambda a1, a2: a1 + a2,
14 map(lambda p: p['altura'], pessoas_altas))
15
16 print(pessoas_altas)
17 if num_pessoas_altas > 0:
18 print(altura_total / num_pessoas_altas)
1 import operator
3 pessoas = [{'nome': 'Pedro', 'altura': 189},
4 {'nome': 'Maíra', 'altura': 173},
5 {'nome': 'Julia', 'altura': 162},
6 {'nome': 'César', 'altura': 186},
7 {'nome': 'Cláudia', 'altura': 162}]
8
9 limite_altura = 180
10 pessoas_altas = filter(lambda p: 'altura' in p
and p['altura'] > limite_altura,
11 pessoas)
12
13 num_pessoas_altas = len(pessoas_altas)
14
15 altura_total = reduce(operator.add,
16 map(lambda p: p['altura'], pessoas_altas))
17
18 print(pessoas_altas)
19 if num_pessoas_altas > 0:
20 print(altura_total / num_pessoas_altas)
1 import operator
3 pessoas = [{'nome': 'Pedro', 'altura': 189},
4 {'nome': 'Maíra', 'altura': 173},
5 {'nome': 'Julia', 'altura': 162},
6 {'nome': 'César', 'altura': 186},
7 {'nome': 'Cláudia', 'altura': 162}]
8
9 limite_altura = 180
10 pessoas_altas = filter(lambda p: 'altura' in p
and p['altura'] > limite_altura,
11 pessoas)
12
13 num_pessoas_altas = len(pessoas_altas)
14
15 altura_total = reduce(operator.add,
16 map(lambda p: p['altura'], pessoas_altas))
17
18 print(pessoas_altas)
19 if num_pessoas_altas > 0:
20 print(altura_total / num_pessoas_altas)
1 sum(list) == reduce(operator.add, list)
1 pessoas = [{'nome': 'Pedro', 'altura': 189},
2 {'nome': 'Maíra', 'altura': 173},
3 {'nome': 'Julia', 'altura': 162},
4 {'nome': 'César', 'altura': 186},
5 {'nome': 'Cláudia', 'altura': 162}]
6
7 limite_altura = 180
8 pessoas_altas = filter(lambda p: 'altura' in p
and p['altura'] > limite_altura,
9 pessoas)
10
11 num_pessoas_altas = len(pessoas_altas)
12 altura_total = sum(map(lambda p: p['altura'], pessoas_altas))
13
14 print(pessoas_altas)
15 if num_pessoas_altas > 0:
16 print(altura_total / num_pessoas_altas)
Dúvidas?
Roteiro
• O que é programação funcional?
• Por que programação funcional importa?
• Programando funcionalmente na prática
Java
• Java 8 Stream API
• Java 8 Lambdas
• Linguagens: Scala, Kotlin, Clojure
C#
• LINQ
• Tuplas
• Listas Funcionais
• Linguagens: F#, OCaml
JavaScript
• Ramda.js
• Immutable.js
• Listas Funcionais
• Eloquent JavaScript Cap. 6
• Linguagens: PureScript, ClojureScript
C/C++
• C++11 & C++17
• Lambdas, std::function
• Combinadores STL
• Linguagens: Rust, Swift, Kotlin
Outros?
Dúvidas?
Muito obrigado!

Mais conteúdo relacionado

Mais procurados

Aula: busca e ordenação
Aula: busca e ordenaçãoAula: busca e ordenação
Aula: busca e ordenaçãoRodrigo Rocha
 
Leonardo Zamariola - High Order Functions e Functional Interfaces
Leonardo Zamariola - High Order Functions e Functional InterfacesLeonardo Zamariola - High Order Functions e Functional Interfaces
Leonardo Zamariola - High Order Functions e Functional InterfacesDevCamp Campinas
 
1 interpol polinomial_met_lagrange_newton
1 interpol polinomial_met_lagrange_newton1 interpol polinomial_met_lagrange_newton
1 interpol polinomial_met_lagrange_newtonClaudiana Furtado
 
Iteráveis e geradores (versão RuPy)
Iteráveis e geradores (versão RuPy)Iteráveis e geradores (versão RuPy)
Iteráveis e geradores (versão RuPy)Luciano Ramalho
 
(2015-01-29/30) [WTA2015] Adaptatividade em Python (Tutorial)
(2015-01-29/30) [WTA2015] Adaptatividade em Python (Tutorial)(2015-01-29/30) [WTA2015] Adaptatividade em Python (Tutorial)
(2015-01-29/30) [WTA2015] Adaptatividade em Python (Tutorial)Danilo J. S. Bellini
 
Paradigmas de Linguagens de Programacao - Aula #3
Paradigmas de Linguagens de Programacao - Aula #3Paradigmas de Linguagens de Programacao - Aula #3
Paradigmas de Linguagens de Programacao - Aula #3Ismar Silveira
 
Classes de complexidades de problemas
Classes de complexidades de problemasClasses de complexidades de problemas
Classes de complexidades de problemasDavid Achahui Perez
 
Trabalho parte 7 e 8
Trabalho parte 7 e 8Trabalho parte 7 e 8
Trabalho parte 7 e 8jean machado
 

Mais procurados (13)

Aula: busca e ordenação
Aula: busca e ordenaçãoAula: busca e ordenação
Aula: busca e ordenação
 
Leonardo Zamariola - High Order Functions e Functional Interfaces
Leonardo Zamariola - High Order Functions e Functional InterfacesLeonardo Zamariola - High Order Functions e Functional Interfaces
Leonardo Zamariola - High Order Functions e Functional Interfaces
 
1 interpol polinomial_met_lagrange_newton
1 interpol polinomial_met_lagrange_newton1 interpol polinomial_met_lagrange_newton
1 interpol polinomial_met_lagrange_newton
 
Monadic Design
Monadic DesignMonadic Design
Monadic Design
 
16598764 apostila-de-calculo
16598764 apostila-de-calculo16598764 apostila-de-calculo
16598764 apostila-de-calculo
 
Metodos de ordenação em c#
Metodos de ordenação em c#Metodos de ordenação em c#
Metodos de ordenação em c#
 
Derivadas
DerivadasDerivadas
Derivadas
 
Iteráveis e geradores (versão RuPy)
Iteráveis e geradores (versão RuPy)Iteráveis e geradores (versão RuPy)
Iteráveis e geradores (versão RuPy)
 
Java 8 - New Features
Java 8 - New FeaturesJava 8 - New Features
Java 8 - New Features
 
(2015-01-29/30) [WTA2015] Adaptatividade em Python (Tutorial)
(2015-01-29/30) [WTA2015] Adaptatividade em Python (Tutorial)(2015-01-29/30) [WTA2015] Adaptatividade em Python (Tutorial)
(2015-01-29/30) [WTA2015] Adaptatividade em Python (Tutorial)
 
Paradigmas de Linguagens de Programacao - Aula #3
Paradigmas de Linguagens de Programacao - Aula #3Paradigmas de Linguagens de Programacao - Aula #3
Paradigmas de Linguagens de Programacao - Aula #3
 
Classes de complexidades de problemas
Classes de complexidades de problemasClasses de complexidades de problemas
Classes de complexidades de problemas
 
Trabalho parte 7 e 8
Trabalho parte 7 e 8Trabalho parte 7 e 8
Trabalho parte 7 e 8
 

Semelhante a Programação Funcional (para humanos)

Refatoração de código com Capitão Nascimento versão completa
Refatoração de código com Capitão Nascimento versão completaRefatoração de código com Capitão Nascimento versão completa
Refatoração de código com Capitão Nascimento versão completaEduardo Bregaida
 
Estruturas de dados em Python
Estruturas de dados em PythonEstruturas de dados em Python
Estruturas de dados em PythonRicardo Paiva
 
113856859 exercicios-vetor-e-matriz
113856859 exercicios-vetor-e-matriz113856859 exercicios-vetor-e-matriz
113856859 exercicios-vetor-e-matrizDaniel Natividade
 
Aula - Funções (Curso de Python Básico -- FATEC SENAI MT)
Aula - Funções (Curso de Python Básico -- FATEC SENAI MT)Aula - Funções (Curso de Python Básico -- FATEC SENAI MT)
Aula - Funções (Curso de Python Básico -- FATEC SENAI MT)Filipe Chagas Ferraz
 
IEEEweek 2017 @ DETI Univ. Aveiro - Workshop Python
IEEEweek 2017 @ DETI Univ. Aveiro - Workshop PythonIEEEweek 2017 @ DETI Univ. Aveiro - Workshop Python
IEEEweek 2017 @ DETI Univ. Aveiro - Workshop PythonDiogo Gomes
 
RevisãoCompactaFuncoesPonteiro.pptx
RevisãoCompactaFuncoesPonteiro.pptxRevisãoCompactaFuncoesPonteiro.pptx
RevisãoCompactaFuncoesPonteiro.pptxClaudia Ferlin
 
Programação em Python_6.pptx
Programação em Python_6.pptxProgramação em Python_6.pptx
Programação em Python_6.pptxzarusca
 
Semana 11: Enumerações, limites de tipos numéricos (gama e precisão)
Semana 11: Enumerações, limites de tipos numéricos (gama e precisão)Semana 11: Enumerações, limites de tipos numéricos (gama e precisão)
Semana 11: Enumerações, limites de tipos numéricos (gama e precisão)Manuel Menezes de Sequeira
 
Programação Estruturada 2 - Aula 02
Programação Estruturada 2 - Aula 02Programação Estruturada 2 - Aula 02
Programação Estruturada 2 - Aula 02thomasdacosta
 
Aplicação do k-NN utilizando Bitonic Sort
Aplicação do k-NN utilizando Bitonic SortAplicação do k-NN utilizando Bitonic Sort
Aplicação do k-NN utilizando Bitonic SortVinicius Coelho
 
Algoritmos e Estrutura de Dados - Aula 03
Algoritmos e Estrutura de Dados - Aula 03Algoritmos e Estrutura de Dados - Aula 03
Algoritmos e Estrutura de Dados - Aula 03thomasdacosta
 
Controle con matlab - material adicional 1.pdf
Controle con matlab - material adicional 1.pdfControle con matlab - material adicional 1.pdf
Controle con matlab - material adicional 1.pdfCarlosAlexisAlvarado4
 
Estrutura de dados
Estrutura de dadosEstrutura de dados
Estrutura de dadosgjpbg
 
Apostila estrutura de dados 2
Apostila estrutura de dados 2Apostila estrutura de dados 2
Apostila estrutura de dados 2Leandro Lopes
 
Beljug2010
Beljug2010Beljug2010
Beljug2010UFPA
 

Semelhante a Programação Funcional (para humanos) (20)

Refatoração de código com Capitão Nascimento versão completa
Refatoração de código com Capitão Nascimento versão completaRefatoração de código com Capitão Nascimento versão completa
Refatoração de código com Capitão Nascimento versão completa
 
Estruturas de dados em Python
Estruturas de dados em PythonEstruturas de dados em Python
Estruturas de dados em Python
 
Design OO
Design OODesign OO
Design OO
 
113856859 exercicios-vetor-e-matriz
113856859 exercicios-vetor-e-matriz113856859 exercicios-vetor-e-matriz
113856859 exercicios-vetor-e-matriz
 
Aula - Funções (Curso de Python Básico -- FATEC SENAI MT)
Aula - Funções (Curso de Python Básico -- FATEC SENAI MT)Aula - Funções (Curso de Python Básico -- FATEC SENAI MT)
Aula - Funções (Curso de Python Básico -- FATEC SENAI MT)
 
IEEEweek 2017 @ DETI Univ. Aveiro - Workshop Python
IEEEweek 2017 @ DETI Univ. Aveiro - Workshop PythonIEEEweek 2017 @ DETI Univ. Aveiro - Workshop Python
IEEEweek 2017 @ DETI Univ. Aveiro - Workshop Python
 
RevisãoCompactaFuncoesPonteiro.pptx
RevisãoCompactaFuncoesPonteiro.pptxRevisãoCompactaFuncoesPonteiro.pptx
RevisãoCompactaFuncoesPonteiro.pptx
 
Programação em Python_6.pptx
Programação em Python_6.pptxProgramação em Python_6.pptx
Programação em Python_6.pptx
 
Introdução ao paradigma funcional com scala
Introdução ao paradigma funcional com scalaIntrodução ao paradigma funcional com scala
Introdução ao paradigma funcional com scala
 
Semana 11: Enumerações, limites de tipos numéricos (gama e precisão)
Semana 11: Enumerações, limites de tipos numéricos (gama e precisão)Semana 11: Enumerações, limites de tipos numéricos (gama e precisão)
Semana 11: Enumerações, limites de tipos numéricos (gama e precisão)
 
Programação Estruturada 2 - Aula 02
Programação Estruturada 2 - Aula 02Programação Estruturada 2 - Aula 02
Programação Estruturada 2 - Aula 02
 
Aplicação do k-NN utilizando Bitonic Sort
Aplicação do k-NN utilizando Bitonic SortAplicação do k-NN utilizando Bitonic Sort
Aplicação do k-NN utilizando Bitonic Sort
 
Algoritmos e Estrutura de Dados - Aula 03
Algoritmos e Estrutura de Dados - Aula 03Algoritmos e Estrutura de Dados - Aula 03
Algoritmos e Estrutura de Dados - Aula 03
 
apostila C++
apostila C++apostila C++
apostila C++
 
Controle con matlab - material adicional 1.pdf
Controle con matlab - material adicional 1.pdfControle con matlab - material adicional 1.pdf
Controle con matlab - material adicional 1.pdf
 
Estrutura de dados
Estrutura de dadosEstrutura de dados
Estrutura de dados
 
Apostila estrutura de dados 2
Apostila estrutura de dados 2Apostila estrutura de dados 2
Apostila estrutura de dados 2
 
Java4
Java4Java4
Java4
 
Beljug2010
Beljug2010Beljug2010
Beljug2010
 
App scala
App scalaApp scala
App scala
 

Programação Funcional (para humanos)

  • 1. Programação Funcional (Para humanos) Pedro Castilho 20/06/2017 plc@cin.ufpe.br
  • 2. Pedro Castilho (Unicórnios são muito importantes na programação funcional) • 9˚ período de EC (tecnicamente) • Viciado em programação funcional • Lisper desde 2011 • Ex-monitor de PLC
  • 3. Pedro Castilho (Morrendo de medo de bater água no notebook) • Competidor IoT internacional
  • 4. Pedro Castilho (Baixem na app store, beijos) • Competidor IoT internacional • Desenvolvedor iOS
  • 5. Pedro Castilho (Infelizmente não posso dar muitos detalhes) • Competidor IoT internacional • Desenvolvedor iOS • Estagiário (mobile híbrido)
  • 8. Roteiro • O que é programação funcional? • Por que programação funcional importa? • Programando funcionalmente na prática
  • 9. Roteiro • O que é programação funcional? • Por que programação funcional importa? • Programando funcionalmente na prática
  • 10. O que a maioria das pessoas espera 1 (defn (assign-cluster pt centres) 2 (let* ((distances (map 3 (lambda (centre) (euclidean-distance centre pt)) 4 centres)) 5 (smallest (apply min distances))) 6 (list-index (lambda (d) (= d smallest)) distances)))
  • 11. O que a maioria das pessoas espera 1 kMeansPP :: MonadRandom m => Int -> [Vec] -> m [Cluster] 2 kMeansPP n pts = kMeansIteration pts <$> centroids 3 where centroids = iterate (>>= nextCentroid) x0 !! (n-1) 4 x0 = take 1 <$> randomElements pts 5 nextCentroid cs = (: cs) <$> fromList (map (weight cs) pts) 6 weight cs x = (x, toRational $ distance x (cs `nearestTo` x))
  • 12. Hoje não vai ser assim.
  • 13. Você NÃO precisa: • Ser um “monstro" da programação • Saber matemática complexa • Saber uma linguagem funcional • Ter cursado PLC • Saber usar Monads
  • 15. Problema: Converter os valores de uma lista/array
  • 16. 1 using System; 2 3 namespace Ex1 { 4 interface IConversor<T, U> { 5 U Converter(T valor); 6 } 7 8 class Programa { 9 static U[] Converter<T, U>(T[] entrada, IConversor<T, U> conversor) { 10 U[] resultado = new U[input.length]; 11 12 for (int i = 0; i < input.length; i++) { 13 resultado[i] = conversor.Converter(entrada[i]); 14 } 15 16 return resultado; 17 }
  • 17. 18 19 class ConversorQuadrado: IConversor<int, string> { 20 public string Converter(int i) { 21 return (i * i).toString(); 22 } 23 } 24 25 class ConversorEscala: IConversor<int, string> { 26 readonly int Escala; 27 28 public ConversorEscala(int escala) { 29 this.Escala = escala; 30 } 31 32 public string Converter(int i) { 33 return (i * escala).toString(); 34 } 35 }
  • 18. 36 37 static void Main(string[] args) { 38 int[] nums = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; 39 40 string[] qnums = Converter<int, string>(nums, new ConversorQuadrado()); 41 string[] tnums = Converter<int, string>(nums, new ConversorEscala(3)); 42 Console.WriteLine(string.Join(", ", qnums)); 43 Console.WriteLine(string.Join(", ", tnums)); 44 } 45 } 46 }
  • 19. Agora em um estilo mais funcional:
  • 20. 1 func converter<T, U>(_ entrada: [T], usando conversor: (T) -> U) -> [U] { 2 var resultado: [T] = [] 3 for valor in entrada { 4 resultado.append(conversor(valor)) 5 } 6 return resultado 7 } 8 9 func conversorQuadrado(_ i: Int) -> String { 10 return String(i * i) 11 } 12 13 func conversorEscala(_ i: Int, escala: Int) -> String { 14 return String(escala * i) 15 } 16 17 let nums = Array<Int>(1...10) 18 let qnums = converter(nums, usando: conversorQuadrado) 19 print(", ".join(qnums)) 20 // e a escala?
  • 21. 1 func converter<T, U>(_ entrada: [T], usando conversor: (T) -> U) -> [U] { 2 var resultado: [T] = [] 3 for valor in entrada { 4 resultado.append(conversor(valor)) 5 } 6 return resultado 7 } 8 9 func conversorQuadrado(_ i: Int) -> String { 10 return String(i * i) 11 } 12 13 func conversorEscala(escala: Int) -> ((Int) -> String) { 14 return { x in x * escala } 15 } 16 17 let nums = Array<Int>(1...10) 18 let qnums = converter(nums, usando: conversorQuadrado) 19 print(", ".join(qnums)) 20 let tnums = converter(nums, usando: conversorEscala(3))
  • 24. Funções de Primeira Classe • Podem ser guardadas em variáveis • Podem ser passadas como argumentos • Podem ser retornadas de funções • Compõem comportamentos complexos
  • 25. 1 func converter<T, U>(_ entrada: [T], usando conversor: (T) -> U) -> [U] { 2 return entrada.map(conversor) 3 } 4 5 func conversorQuadrado(_ i: Int) -> String { 6 return String(i * i) 7 } 8 9 func conversorEscala(escala: Int) -> ((Int) -> String) { 10 return { x in x * escala } 11 } 12 13 let nums = Array<Int>(1...10) 14 let qnums = converter(nums, usando: conversorQuadrado) 15 print(", ".join(qnums)) 16 let tnums = converter(nums, usando: conversorEscala(3)) 17 print(", ".join(tnums))
  • 26. Funções de Primeira Classe Fundamentais • map: Transforma cada elemento de uma lista/array • filter: Remove elementos de uma lista/array • reduce: Produz um resultado agregado de uma lista/array
  • 27. Funções de Primeira Classe Fundamentais map(f, l) l = f =
  • 28. Funções de Primeira Classe Fundamentais map(f, l) l = f =
  • 29. Funções de Primeira Classe Fundamentais map(f, l) l = f =
  • 30. Funções de Primeira Classe Fundamentais map(f, l) l = f =
  • 31. Funções de Primeira Classe Fundamentais map(f, l) resultado = f = l =
  • 32. Funções de Primeira Classe Fundamentais filter(f, l) resultado = f = l = ?
  • 33. Funções de Primeira Classe Fundamentais reduce(f, z, l) resultado = f = l = z =
  • 34. Funções de Primeira Classe Fundamentais reduce(f, z, l) resultado = f = l = z =
  • 35. Funções de Primeira Classe Fundamentais reduce(f, z, l) resultado = f = l = z =
  • 36. Funções de Primeira Classe Fundamentais • Disponíveis em quase qualquer linguagem hoje • Em C#: Usando LINQ • Em Java: Usando Streams • Em Python: Parte da biblioteca padrão
  • 37. 1 using System; 2 using System.Linq; 3 4 namespace Ex1 { 5 class Programa { 6 static U[] Converter<T, U>(T[] input, Func<T, U> conversor) { 7 return input.Select(valor => conversor(valor)).ToArray(); 8 } 9 10 static void Main(string[] args) { 11 int[] nums = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; 12 13 string[] qnums = Converter<int, string>(nums, x => x * x); 14 string[] tnums = Converter<int, string>(nums, x => 3 * x); 15 Console.WriteLine(string.Join(", ", qnums)); 16 Console.WriteLine(string.Join(", ", tnums)); 17 } 18 } 19 }
  • 40. 1 let nums = Array<Int>(1...10) 2 let qnums = nums.map({ i in String(i * i) }) 3 print(", ".join(qnums)) 4 let tnums = nums.map({ i in String(i * 3) }) 5 print(", ".join(tnums))
  • 43. Sintaxe Java: C#:
 
 JavaScript ES6: JavaScript ES5: Python: Ruby: Swift: (argumentos) -> { código } argumentos => { código } (argumentos) => { código } function(argumentos) { código } lambda argumentos: código |argumentos| { código } { argumentos in código }
  • 44. Roteiro • O que é programação funcional? • Por que programação funcional importa? • Programando funcionalmente na prática
  • 45. 1 pessoas = [{'nome': 'Pedro', 'altura': 189}, 2 {'nome': 'Maíra', 'altura': 173}, 3 {'nome': 'Julia', 'altura': 162}, 4 {'nome': 'César', 'altura': 186}, 5 {'nome': 'Cláudia', 'altura': 162}]
  • 46. 1 pessoas = [{'nome': 'Pedro', 'altura': 189}, 2 {'nome': 'Maíra', 'altura': 173}, 3 {'nome': 'Julia', 'altura': 162}, 4 {'nome': 'César', 'altura': 186}, 5 {'nome': 'Cláudia', 'altura': 162}]
  • 47. Problema: Imprimir as pessoas com altura acima de 1,80m
  • 48. 1 pessoas = [{'nome': 'Pedro', 'altura': 189}, 2 {'nome': 'Maíra', 'altura': 173}, 3 {'nome': 'Julia', 'altura': 162}, 4 {'nome': 'César', 'altura': 186}, 5 {'nome': 'Cláudia', 'altura': 162}] 6 7 limite_altura = 180 8 pessoas_altas = [] 9 for pessoa in pessoas: 10 if 'altura' in pessoa and pessoa['altura'] > limite_altura: 11 pessoas_altas.append(pessoa) 12 13 print(pessoas_altas)
  • 49. 1 pessoas = [{'nome': 'Pedro', 'altura': 189}, 2 {'nome': 'Maíra', 'altura': 173}, 3 {'nome': 'Julia', 'altura': 162}, 4 {'nome': 'César', 'altura': 186}, 5 {'nome': 'Cláudia', 'altura': 162}] 6 7 limite_altura = 180 8 pessoas_altas = filter(lambda p: 'altura' in p and p['altura'] > limite_altura, 9 pessoas) 10 11 print(pessoas_altas)
  • 50. Novo Problema: Também imprimir a altura média das pessoas com altura acima de 1,80m
  • 51. 1 pessoas = [{'nome': 'Pedro', 'altura': 189}, 2 {'nome': 'Maíra', 'altura': 173}, 3 {'nome': 'Julia', 'altura': 162}, 4 {'nome': 'César', 'altura': 186}, 5 {'nome': 'Cláudia', 'altura': 162}] 6 7 limite_altura = 180 8 pessoas_altas = [] 9 altura_total = 0 10 for pessoa in pessoas: 11 if 'altura' in pessoa and pessoa['altura'] > limite_altura: 12 pessoas_altas.append(pessoa) 13 altura_total += pessoa['altura'] 14 15 print(pessoas_altas) 16 if len(pessoas_altas) > 0: 17 media_altura = altura_total / len(pessoas_altas)
  • 52. 1 pessoas = [{'nome': 'Pedro', 'altura': 189}, 2 {'nome': 'Maíra', 'altura': 173}, 3 {'nome': 'Julia', 'altura': 162}, 4 {'nome': 'César', 'altura': 186}, 5 {'nome': 'Cláudia', 'altura': 162}] 6 7 limite_altura = 180 8 pessoas_altas = filter(lambda p: 'altura' in p and p['altura'] > limite_altura, 9 pessoas) 10 11 num_pessoas_altas = len(pessoas_altas) 12 13 altura_total = reduce(lambda a1, a2: a1 + a2, 14 map(lambda p: p['altura'], pessoas_altas)) 15 16 print(pessoas_altas) 17 if num_pessoas_altas > 0: 18 print(altura_total / num_pessoas_altas)
  • 53. 1 import operator 3 pessoas = [{'nome': 'Pedro', 'altura': 189}, 4 {'nome': 'Maíra', 'altura': 173}, 5 {'nome': 'Julia', 'altura': 162}, 6 {'nome': 'César', 'altura': 186}, 7 {'nome': 'Cláudia', 'altura': 162}] 8 9 limite_altura = 180 10 pessoas_altas = filter(lambda p: 'altura' in p and p['altura'] > limite_altura, 11 pessoas) 12 13 num_pessoas_altas = len(pessoas_altas) 14 15 altura_total = reduce(operator.add, 16 map(lambda p: p['altura'], pessoas_altas)) 17 18 print(pessoas_altas) 19 if num_pessoas_altas > 0: 20 print(altura_total / num_pessoas_altas)
  • 54. 1 import operator 3 pessoas = [{'nome': 'Pedro', 'altura': 189}, 4 {'nome': 'Maíra', 'altura': 173}, 5 {'nome': 'Julia', 'altura': 162}, 6 {'nome': 'César', 'altura': 186}, 7 {'nome': 'Cláudia', 'altura': 162}] 8 9 limite_altura = 180 10 pessoas_altas = filter(lambda p: 'altura' in p and p['altura'] > limite_altura, 11 pessoas) 12 13 num_pessoas_altas = len(pessoas_altas) 14 15 altura_total = reduce(operator.add, 16 map(lambda p: p['altura'], pessoas_altas)) 17 18 print(pessoas_altas) 19 if num_pessoas_altas > 0: 20 print(altura_total / num_pessoas_altas)
  • 55. 1 sum(list) == reduce(operator.add, list)
  • 56. 1 pessoas = [{'nome': 'Pedro', 'altura': 189}, 2 {'nome': 'Maíra', 'altura': 173}, 3 {'nome': 'Julia', 'altura': 162}, 4 {'nome': 'César', 'altura': 186}, 5 {'nome': 'Cláudia', 'altura': 162}] 6 7 limite_altura = 180 8 pessoas_altas = filter(lambda p: 'altura' in p and p['altura'] > limite_altura, 9 pessoas) 10 11 num_pessoas_altas = len(pessoas_altas) 12 altura_total = sum(map(lambda p: p['altura'], pessoas_altas)) 13 14 print(pessoas_altas) 15 if num_pessoas_altas > 0: 16 print(altura_total / num_pessoas_altas)
  • 58. Roteiro • O que é programação funcional? • Por que programação funcional importa? • Programando funcionalmente na prática
  • 59. Java • Java 8 Stream API • Java 8 Lambdas • Linguagens: Scala, Kotlin, Clojure
  • 60. C# • LINQ • Tuplas • Listas Funcionais • Linguagens: F#, OCaml
  • 61. JavaScript • Ramda.js • Immutable.js • Listas Funcionais • Eloquent JavaScript Cap. 6 • Linguagens: PureScript, ClojureScript
  • 62. C/C++ • C++11 & C++17 • Lambdas, std::function • Combinadores STL • Linguagens: Rust, Swift, Kotlin