Slide 1

Slide 1 text

Programação Funcional em PHP saia da zona de conforto Marcel Gonçalves dos Santos @marcelgsantos λ

Slide 2

Slide 2 text

pensandonaweb.com.br desenvolvedor web full-stack Marcel Gonçalves dos Santos @marcelgsantos

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

@femugsp sp.femug.com

Slide 5

Slide 5 text

@phpsp phpsp.org.br

Slide 6

Slide 6 text

Learning OOP in PHP Tutoriais, vídeos, slides, livros sobre OOP, OOD, design patterns, refatoração e arquitetura. bit.ly/Learning-OOP-in-PHP

Slide 7

Slide 7 text

Interaja nas mídias sociais!
 
 - fale sobre o evento, palestrantes e conteúdo - tire fotos do evento e publique
 - interaja com outros participantes do evento - tire dúvidas ou dê feedbacks para os palestrantes

Slide 8

Slide 8 text

1. seguir @marcelgsantos no Twitter
 2. tuitar utilizando as hashtags #phpmgconf,
 #funcional e #php
 3. não vale tuíte em branco e retuíte
 4. ler e preencher este simples formulário
 bit.ly/sorteio-phpmg Concorra a um livro da Casa do Código!

Slide 9

Slide 9 text

O que é programação funcional?

Slide 10

Slide 10 text

é um paradigma de programação que utiliza funções puras e foca na transformação do estado

Slide 11

Slide 11 text

O que é paradigma de programação?

Slide 12

Slide 12 text

são modelos ou estilos de programação suportados por linguagens que agrupam certas características comuns

Slide 13

Slide 13 text

Os paradigmas de programação definem como os códigos são estruturados.

Slide 14

Slide 14 text

principais paradigmas de programação
 os dois principais paradigmas são o imperativo e o declarativo

Slide 15

Slide 15 text

paradigma imperativo
 descreve a resolução de um problema através de comandos que o computador pode compreender e executar

Slide 16

Slide 16 text

paradigma imperativo
 os paradigmas procedural e orientado a objetos são exemplos de paradigmas imperativos

Slide 17

Slide 17 text

!// Imperative code to sum 1 to 10
 $sum = 0; for ($i = 1; $i !<= 10; $i!++) { $sum += $i; } print $sum; !// 55

Slide 18

Slide 18 text

paradigma declarativo
 permite especificar o que deve ser computado e não como deve ser computado

Slide 19

Slide 19 text

paradigma declarativo
 os paradigmas funcional e lógico são exemplos de paradigmas declarativos

Slide 20

Slide 20 text

!// Declarative code to sum 1 to 10 print array_sum(range(1, 10)); !// 55

Slide 21

Slide 21 text

paradigmas de linguagens de programação
 
 imperativo
 procedural - C e Pascal orientado a objetos - C++, Java, JavaScript, PHP, Python e Ruby
 
 declarativo
 lógico - Prolog funcional - Clojure, Elixir, Elm, Erlang, F#, Haskell, Lisp, OCaml e Scala

Slide 22

Slide 22 text

Programação
 Funcional λ

Slide 23

Slide 23 text

paradigma de programação que utiliza funções puras e foca na transformação do estado

Slide 24

Slide 24 text

baseado no cálculo lambda proposto por Alonzo Church na década de 30

Slide 25

Slide 25 text

na programação funcional as funções são tratadas como conceito principal

Slide 26

Slide 26 text

Uma função matemática trata-se de um simples mapeamento entre o domínio e o contra-domínio. 1 2 3 D B A C X Y

Slide 27

Slide 27 text

Estado λ

Slide 28

Slide 28 text

o estado de um programa é representado pelos valores dos dados armazenados na memória…

Slide 29

Slide 29 text

…em qualquer ponto de execução do programa

Slide 30

Slide 30 text

o estado de uma aplicação é alterado a cada interação feita pelo usuário ou pelo próprio sistema…

Slide 31

Slide 31 text

…e pode ser representado por uma estrutura de dados

Slide 32

Slide 32 text

a maioria dos bugs são relacionados ao controle de estado

Slide 33

Slide 33 text

Funções Puras λ

Slide 34

Slide 34 text

funções puras
 
 1. ter parâmetros de entrada 
 2. não depender do estado externo 
 3. retorno baseado nos valores de entrada 
 4. não devem causar efeitos colaterais

Slide 35

Slide 35 text

!// pure or impure function? $counter = 0; $increment = function () use (&$counter) { $counter!++; return $counter; }; print $increment(); !// 1

Slide 36

Slide 36 text

!// pure function function add($x, $y) { return $x + $y; } print add(2, 3); !// 5

Slide 37

Slide 37 text

!// pure function using closure syntax $add = function ($x, $y) { return $x + $y; }; print $add(2, 3); !// 5

Slide 38

Slide 38 text

!// pure function using arrow function
 !// syntax (PHP 7.4) $add = fn($x, $y) !=> $x + $y; print $add(2, 3); !// 5

Slide 39

Slide 39 text

por que utilizar funções puras?
 são reutilizáveis, componíveis, fáceis de testar, fáceis de cachear e paralelizáveis

Slide 40

Slide 40 text

transparência referencial
 propriedade que garante que a saída de uma função pura sempre será a mesma dado um mesmo conjunto de argumentos

Slide 41

Slide 41 text

!// referential transparency $add = fn($x, $y) !=> $x + $y; var_dump($add(2, 3) !!=== 5); !// true var_dump(5 !!=== 5); !// true

Slide 42

Slide 42 text

pode não ser fácil criar funções puras

Slide 43

Slide 43 text

porém, a restritividade ajuda a melhorar o foco

Slide 44

Slide 44 text

Mais sobre
 Funções λ

Slide 45

Slide 45 text

funções de primeira classe
 são funções que podem ser tratadas como valores, ou seja, podem ser atribuídas a variáveis, passadas como argumentos e retornadas de uma função

Slide 46

Slide 46 text

!// first-class function $add = fn($x, $y) !=> $x + $y; $numbers = [1, 2, 3, 4, 5]; $sum = array_reduce($numbers, $add); $sum10 = array_reduce($numbers, $add, 10); print $sum; !// 15 print $sum10; !// 25

Slide 47

Slide 47 text

!// first-class function $add = fn($x, $y) !=> $x + $y; $numbers = [1, 2, 3, 4, 5]; $sum = array_reduce($numbers, $add); $sum10 = array_reduce($numbers, $add, 10); print $sum; !// 15 print $sum10; !// 25

Slide 48

Slide 48 text

funções de alta ordem
 são funções que operam sobre outras funções

Slide 49

Slide 49 text

!// high-order function $add = fn($x, $y) !=> $x + $y; $numbers = [1, 2, 3, 4, 5]; $sum = array_reduce($numbers, $add); $sum10 = array_reduce($numbers, $add, 10); print $sum; !// 15 print $sum10; !// 25

Slide 50

Slide 50 text

!// high-order function $add = fn($x, $y) !=> $x + $y; $numbers = [1, 2, 3, 4, 5]; $sum = array_reduce($numbers, $add); $sum10 = array_reduce($numbers, $add, 10); print $sum; !// 15 print $sum10; !// 25

Slide 51

Slide 51 text

Os conceitos de funções de primeira classe e funções de alta ordem estão intimamente relacionados, uma não existiria sem a outra.

Slide 52

Slide 52 text

funções anônimas
 funções que não possuem nome e que, geralmente, são passadas como argumento ou atribuídas

Slide 53

Slide 53 text

!// anonymous function $numbers = [1, 2, 3, 4, 5]; $sum = array_reduce($numbers, fn($x, $y) !=> $x + $y); print $sum; !// 15

Slide 54

Slide 54 text

escopo
 uma função lambda ou função anônima tem o seu próprio escopo como qualquer função no PHP

Slide 55

Slide 55 text

escopo
 o escopo é tratado de forma diferente entre as linguagens JavaScript e PHP

Slide 56

Slide 56 text

escopo
 no JavaScript uma função anônima pode acessar uma variável do escopo externo enquanto no PHP isto não é permitido

Slide 57

Slide 57 text

closures
 funções que possuem acesso à valores do escopo externo

Slide 58

Slide 58 text

!// closure function function greet($greeting) { return function ($name) use ($greeting) { return "$greeting $name!"; }; } $greet = fn($greeting) !=> fn($name) !=> "$greeting $name!"; print greet('Hello')('Mary'); !// Hello Mary! print $greet('Hello')('Mary'); !// Hello Mary!

Slide 59

Slide 59 text

closures
 as closures em PHP utilizam a abordagem early-binding, ou seja, as variáveis da closure terão os valores que tinham quando a closure foi definida

Slide 60

Slide 60 text

closures
 isso pode ser sobrescrito utilizando passagem por referência ou redefinindo uma closure

Slide 61

Slide 61 text

funções como objetos
 no PHP as funções são consideradas objetos

Slide 62

Slide 62 text

!// function as object class Hello { public function !__invoke($name) { return "Hello $name!"; } } $hello = new Hello; print $hello('John'); !// Hello John! a classe deve implementar o método __invoke

Slide 63

Slide 63 text

recursão
 é quando uma função é definida em termos de si própria, ou seja, quando a função chama ela mesma

Slide 64

Slide 64 text

!// recursive function function factorial($number) { if ($number !!=== 1) { return 1; } else { return ($number * factorial($number - 1)); } } print factorial(5); !// 120

Slide 65

Slide 65 text

!// recursive function (using closure syntax) $factorial = function ($number) use (&$factorial) { if ($number !!=== 1) { return 1; } else { return ($number * $factorial($number - 1)); } }; print $factorial(5); !// 120

Slide 66

Slide 66 text

diferença entre função e procedimento (procedure)
 uma função recebe um valor e retorna um resultado; um procedimento é um conjunto de comandos executados numa ordem

Slide 67

Slide 67 text

“Don't think of functions as a collection of instructions. Think of them as non-destructive operations on input `double = n => n * 2;`” Eric Elliott, 2016. https:/ /twitter.com/_ericelliott/status/685172918784004097

Slide 68

Slide 68 text

memoize
 técnica que permite que funções custosas sejam cacheadas para execuções posteriores mais rápidas

Slide 69

Slide 69 text

!// expensive cost function memoized $factorial = $memoize(function ($number) use (&$factorial) { sleep(1); !// it takes 1s to run! if ($number !!=== 1) { return 1; } else { return ($number * $factorial($number - 1)); } }); print $factorial(5); !// 120 (after 5s) print $factorial(7); !// 5040 (after 2s)

Slide 70

Slide 70 text

Imutabilidade λ

Slide 71

Slide 71 text

a imutabilidade diz que um dado não pode ser alterado após a sua criação

Slide 72

Slide 72 text

a imutabilidade permite maior confiança e evita que erros ocorram

Slide 73

Slide 73 text

o PHP não possui suporte completo a dados imutáveis de forma nativa

Slide 74

Slide 74 text

porém, algumas técnicas como value objects podem ser utilizadas para alcançar a imutabilidade

Slide 75

Slide 75 text

Currying e
 Aplicação Parcial λ

Slide 76

Slide 76 text

o currying é a técnica que permite transformar uma função que recebe múltiplos argumentos…

Slide 77

Slide 77 text

…em uma função que recebe apenas um argumento e que retorna uma função que aceita os argumentos restantes

Slide 78

Slide 78 text

!// uncurried function
 function greet($greeting, $name) { return "$greeting $name"; } print greet('Good morning', 'Alice'); !// Good morning Alice $greetMorning = greet('Good morning'); !// PHP Fatal error: Uncaught ArgumentCountError: Too !// few arguments to function greet(), 1 passed

Slide 79

Slide 79 text

!// "curried" function function greet($greeting) { return function ($name) use ($greeting) { return "$greeting $name"; }; } $greetMorning = greet('Good morning'); print $greetMorning('Alice'); !// Good morning Alice print greet('Good morning')('Alice'); !// Good morning Alice print greet('Good morning', 'Alice'); !// error!

Slide 80

Slide 80 text

!// "curried" function using arrow function (PHP 7.4) $greet = fn($greeting) !=> fn($name) !=> "$greeting $name!"; $greetMorning = $greet('Good morning'); print $greetMorning('Alice'); !// Good morning Alice print $greet('Good morning')('Alice'); !// Good morning Alice print $greet('Good morning', 'Alice'); !// error!

Slide 81

Slide 81 text

!// curried function using Functional library $greet = curry(function ($greeting, $name) { return "$greeting $name"; }); print $greet('Good morning')('Alice'); !// Good morning Alice print $greet('Good morning', 'Alice'); !// Good morning Alice

Slide 82

Slide 82 text

a aplicação parcial é quando se executa uma função e passa apenas parte de seus argumentos

Slide 83

Slide 83 text

!// using a helper function that allows to perform !// partial application in a regular not curried function $add = function ($x, $y) { return $x + $y; }; $add3 = partial($add, 3); print $add3(2); !// 5

Slide 84

Slide 84 text

a aplicação parcial permite fazer a especialização de uma função mais genérica

Slide 85

Slide 85 text

!// specialization from a curried function !// using partial application $greet = curry(function ($greeting, $name) { return "$greeting $name"; });
 $greetMorning = $greet('Good morning'); print $greetMorning('Alice'); !// Good morning Alice

Slide 86

Slide 86 text

!// specialization from a curried function !// using partial application (PHP 7.4) $greet = curry(fn($greeting, $name) !=> "$greeting $name"); 
 $greetMorning = $greet('Good morning'); print $greetMorning('Alice'); !// Good morning Alice

Slide 87

Slide 87 text

currying e aplicação parcial são recursos muito utilizados em programação funcional

Slide 88

Slide 88 text

na programação funcional deve-se levar em consideração a ordem dos parâmetros

Slide 89

Slide 89 text

os parâmetros mais genéricos devem vir mais para o início e os parâmetros mais específicos devem vir mais para o final

Slide 90

Slide 90 text

o PHP não possui suporte nativo para currying como nas linguagens puramente funcionais Elm ou Haskell

Slide 91

Slide 91 text

Composição
 de Funções λ

Slide 92

Slide 92 text

a composição é o processo de combinar uma ou mais funções para criar uma nova função

Slide 93

Slide 93 text

!// create a function using composition (traditional way) $sentence = 'estava à toa na vida o meu amor me chamou pra ver a banda passar cantando coisas de amor';
 $wordCount = function ($text) { return count(explode(' ', $text)); }; print $wordCount($sentence); !// 19

Slide 94

Slide 94 text

é uma solução elegante e legível e ajuda a evitar a utilização do aninhamento de funções

Slide 95

Slide 95 text

a biblioteca Functional possui uma função que permite criar uma nova função a partir da composição de funções

Slide 96

Slide 96 text

!// create a function using composition $sentence = 'estava à toa na vida o meu amor me chamou pra ver a banda passar cantando coisas de amor'; $wordCount = compose(partial('explode', ' '), 'count'); print $wordCount($sentence); !// 19

Slide 97

Slide 97 text

Diferenças 
 entre OO e FP λ

Slide 98

Slide 98 text

um objeto possui características, comportamentos e estado atual e realiza operações sobre o seu próprio estado

Slide 99

Slide 99 text

uma função não faz alterações diretas no estado e, sim, retorna novas transformações do estado atual

Slide 100

Slide 100 text

Caso de 
 Uso λ

Slide 101

Slide 101 text

Caso de Uso 1
 somar os preços dos produtos de um carrinho de compra

Slide 102

Slide 102 text

!// shopping cart $cart = [ ['id' !=> 1, 'product' !=> 'iPhone', 'price' !=> 499], ['id' !=> 2, 'product' !=> 'Kindle', 'price' !=> 179], ['id' !=> 3, 'product' !=> 'MacBook Pro', 'price' !=> 1199], ]; $total = 0; !// get price from shopping cart and sum them !// imperative way (using for-loop and accumulator) for ($i = 0; $i < count($cart); $i!++) { $total += $cart[$i]['price']; } print $total; !// 1877 Passo 1

Slide 103

Slide 103 text

!// shopping cart $cart = [ ['id' !=> 1, 'product' !=> 'iPhone', 'price' !=> 499], ['id' !=> 2, 'product' !=> 'Kindle', 'price' !=> 179], ['id' !=> 3, 'product' !=> 'MacBook Pro', 'price' !=> 1199], ]; !// get prices from shopping cart and sum them !// functional way (intermediate values) $cartPrices = map(fn($item) !=> $item['price'], $cart); $total = sum($cartPrices); print $total; !// 1877 Passo 2 realiza o mapeamento da lista de produtos (objetos) para uma lista de preços (números) faz a somatória da lista de números e retorna o total

Slide 104

Slide 104 text

!// shopping cart $cart = [ ['id' !=> 1, 'product' !=> 'iPhone', 'price' !=> 499], ['id' !=> 2, 'product' !=> 'Kindle', 'price' !=> 179], ['id' !=> 3, 'product' !=> 'MacBook Pro', 'price' !=> 1199], ]; !// get prices from shopping cart and sum them !// functional way (functional composition) $totalCart = compose( map(fn($item) !=> $item['price']), 'f\sum' ); print $totalCart($cart); !// 1877 Passo 3 cria uma nova função a partir da composição de funções e elimina valores intermediários aplicação parcial da função map

Slide 105

Slide 105 text

Outras
 Bibliotecas λ

Slide 106

Slide 106 text

bibliotecas
 
 1. lstrojny/functional-php
 2. kapolos/pramda
 3. sergiors/prelude
 4. widmogrod/php-functional
 5. nikic/iter
 6. leocavalcante/siler
 7. ihor/Nspl " "

Slide 107

Slide 107 text

Conclusão λ

Slide 108

Slide 108 text

as linguagens de programação tradicionais têm adotado conceitos de programação funcional logo é importante conhecê-los

Slide 109

Slide 109 text

por mais que o PHP não tenha um suporte amplo a programação funcional o mindset funcional te ajudará a se tornar um(a) programador(a) melhor

Slide 110

Slide 110 text

a programação funcional não é sobre não ter estado…

Slide 111

Slide 111 text

…e sim sobre eliminar estado e efeito colateral sempre que possível e controlar efeitos colaterais quando necessário

Slide 112

Slide 112 text

foque na transformação do estado e evite efeitos colaterais

Slide 113

Slide 113 text

conhecer bem os paradigmas de programação te permite escolher a melhor ferramenta para cada problema

Slide 114

Slide 114 text

A programação funcional garante o que é código bom em outros paradigmas.

Slide 115

Slide 115 text

existem inúmeros conceitos relacionados a programação funcional como functors, monads, lazy evaluation, tail call optimization…

Slide 116

Slide 116 text

vá em frente e divirta-se!

Slide 117

Slide 117 text

Referências

Slide 118

Slide 118 text

Getting Started with FP in PHP Tutoriais, vídeos, slides, bibliotecas, pessoas influentes sobre programação funcional em PHP. bit.ly/Getting-Started-with-FP-in-PHP

Slide 119

Slide 119 text

Avalie!

Slide 120

Slide 120 text

bit.ly/avalie-palestra-php-funcional

Slide 121

Slide 121 text

Anúncio!

Slide 122

Slide 122 text

bit.ly/workshop-php74 Informações: será apresentado um histórico breve da linguagem, as principais funcionalidades do PHP 7.4 de forma prática como typed properties, arrow functions, spread operator, preloading, FFI entre outras e funcionalidades futuras do PHP 8.0.

Slide 123

Slide 123 text

@marcelgsantos speakerdeck.com/marcelgsantos Obrigado. Perguntas?