Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Elixir: Conjuntos em 3 Atos

Elixir: Conjuntos em 3 Atos

Ato I: porque vale a pena saber usar MapSet em Elixir, com exemplos
práticos de código mais legível e eficiente pelo uso de união,
interseção, diferença etc.;

Ato II: análise da interface de MapSet, e como se compara a conjuntos em outras linguagens modernas importantes;

Ato III: interface versus implementação—como implementei UintSet, um tipo de conjunto para inteiros baseado em um vetor de bits.

Luciano Ramalho

May 25, 2019
Tweet

More Decks by Luciano Ramalho

Other Decks in Programming

Transcript

  1. p o r q u e e c o m

    o CONJUNTOS EM 3 ATOS Porque conjuntos simplificam a lógica,
 e como eles são construídos em Elixir Luciano Ramalho @ramalhoorg Com emojis de gatinhos!
  2. PALESTRA EM 3 ATOS 1
 Porque conjuntos podem simplificar seu

    código 2 2
 Como é a API de MapSet 3
 Como implementar
 uma coleção como MapSet
  3. CASO DE USO #1: RUNE FINDER 4 query = ["FACE"]

    Exibir item se todas as palavras da consulta aparecem na descrição.
  4. CASO DE USO #1: RUNE FINDER 5 query = ["FACE"]

    Exibir item se todas as palavras da consulta aparecem na descrição.
  5. CASO DE USO #1: RUNE FINDER 6 query = ["FACE"]

    Exibir item se todas as palavras da consulta aparecem na descrição.
  6. CASO DE USO #1: RUNE FINDER 8 UnicodeData.txt ... 1F637;FACE

    WITH MEDICAL MASK 1F638;GRINNING CAT FACE WITH SMILING EYES 1F639;CAT FACE WITH TEARS OF JOY 1F63A;SMILING CAT FACE WITH OPEN MOUTH 1F63B;SMILING CAT FACE WITH HEART-SHAPED EYES 1F63C;CAT FACE WITH WRY SMILE 1F63D;KISSING CAT FACE WITH CLOSED EYES 1F63E;POUTING CAT FACE 1F63F;CRYING CAT FACE 1F640;WEARY CAT FACE 1F641;SLIGHTLY FROWNING FACE 1F642;SLIGHTLY SMILING FACE 1F643;UPSIDE-DOWN FACE 1F644;FACE WITH ROLLING EYES ...
  7. CASO DE USO #1: RUNE FINDER 9 query = ["FACE"]

    ... 1F637;FACE WITH MEDICAL MASK 1F638;GRINNING CAT FACE WITH SMILING EYES 1F639;CAT FACE WITH TEARS OF JOY 1F63A;SMILING CAT FACE WITH OPEN MOUTH 1F63B;SMILING CAT FACE WITH HEART-SHAPED EYES 1F63C;CAT FACE WITH WRY SMILE 1F63D;KISSING CAT FACE WITH CLOSED EYES 1F63E;POUTING CAT FACE 1F63F;CRYING CAT FACE 1F640;WEARY CAT FACE 1F641;SLIGHTLY FROWNING FACE 1F642;SLIGHTLY SMILING FACE 1F643;UPSIDE-DOWN FACE 1F644;FACE WITH ROLLING EYES ...
  8. CASO DE USO #1: RUNE FINDER 10 query = ["FACE",

    "CAT"] ... 1F637;FACE WITH MEDICAL MASK 1F638;GRINNING CAT FACE WITH SMILING EYES 1F639;CAT FACE WITH TEARS OF JOY 1F63A;SMILING CAT FACE WITH OPEN MOUTH 1F63B;SMILING CAT FACE WITH HEART-SHAPED EYES 1F63C;CAT FACE WITH WRY SMILE 1F63D;KISSING CAT FACE WITH CLOSED EYES 1F63E;POUTING CAT FACE 1F63F;CRYING CAT FACE 1F640;WEARY CAT FACE 1F641;SLIGHTLY FROWNING FACE 1F642;SLIGHTLY SMILING FACE 1F643;UPSIDE-DOWN FACE 1F644;FACE WITH ROLLING EYES ...
  9. CASO DE USO #1: RUNE FINDER 11 query = ["FACE",

    "CAT", "EYES"] ... 1F637;FACE WITH MEDICAL MASK 1F638;GRINNING CAT FACE WITH SMILING EYES 1F639;CAT FACE WITH TEARS OF JOY 1F63A;SMILING CAT FACE WITH OPEN MOUTH 1F63B;SMILING CAT FACE WITH HEART-SHAPED EYES 1F63C;CAT FACE WITH WRY SMILE 1F63D;KISSING CAT FACE WITH CLOSED EYES 1F63E;POUTING CAT FACE 1F63F;CRYING CAT FACE 1F640;WEARY CAT FACE 1F641;SLIGHTLY FROWNING FACE 1F642;SLIGHTLY SMILING FACE 1F643;UPSIDE-DOWN FACE 1F644;FACE WITH ROLLING EYES ...
  10. CASO DE USO #1: SOLUÇÃO DESCONJUNTADA Já escrevi código assim

    em Go* 12 *Go 1.12 ainda não tem conjuntos na sua biblioteca padrão
  11. CASO DE USO #1: SOLUÇÃO DESCONJUNTADA Já escrevi código assim

    em Go* 13 *Go 1.12 ainda não tem conjuntos na sua biblioteca padrão
  12. CASO DE USO #1: RUNE FINDER 18 www.workcompass.com/ Exibir item

    se todas as palavras da consulta aparecem na descrição.
  13. CASO DE USO #1: RUNE FINDER 19 Q ⊂ D

    www.workcompass.com/ Exibir item se todas as palavras da consulta aparecem na descrição.
  14. CASO DE USO #1: RUNE FINDER 21 Tokenize: transforma query

    e descrição em conjuntos www.workcompass.com/ https://github.com/standupdev/rf
  15. CASO DE USO #1: RUNE FINDER 22 Q ⊂ D

    www.workcompass.com/ https://github.com/standupdev/rf
  16. CASO DE USO #2: GIMEL Outro buscador de emojis, com

    uma estratégia diferente. rf.exs: percorre UnicodeData.txt inteiro a cada consulta; estratégia grep. Gimel: percorre UnicodeData.txt só uma vez ao iniciar, criando dois índices que são usados nas consultas; estratégia índice invertido. 23
  17. COMO FUNCIONA UM ÍNDICE INVERTIDO Para encontrar os três gatinhos,

    pegue a intersecção das ocorrências de "FACE", "CAT", e "EYES": 28
  18. INTERSECÇÃO DAS OCORRÊNCIAS: 3 GATINHOS 29 ⚄ ⾯面 ☹ ὺ

    ⚃ ☺ ⚀ ⚂ ⚁ ☻ ⚅ ꊶ (F ∩ C) ∩ E Face Cat Eyes query = ["FACE", "CAT", "EYES"] Nota: este diagrama não está correto. Deveria haver emojis nas intersecções entre dois conjuntos: F ∩ C, F ∩ E, C ∩ E
  19. CASO DE USO #3: LOJA ONLINE 33 Destacar todos os

    produtos favoritados, exceto aqueles que já estão no carrinho de compras.
  20. CASO DE USO #3: LOJA ONLINE 34 Destacar todos os

    produtos favoritados, exceto aqueles que já estão no carrinho de compras. F ∖ C Diferença entre
 conjuntos:
  21. Nobody has yet discovered a branch of mathematics that has

    successfully resisted formalization into set theory. Thomas Forster
 Logic Induction and Sets, p. 167 36
  22. Ninguém descobriu ainda um ramo da matemática que tenha resistido

    à formalização através da teoria dos conjuntos. Thomas Forster
 Indução Lógica e Conjuntos, p. 167 37
  23. CONJUNÇÃO LÓGICA É INTERSECÇÃO "x pertence à intersecção de A

    com B" é o mesmo que: "x pertence a A e x pertence a B." Em matemática: x ∈ (A ∩ B) ⟺ (x ∈ A) ∧ (x ∈ B) Em Elixir: MapSet.intersection Bitwise.band/2, &&& 38
  24. DISJUNÇÃO LÓGICA É UNIÃO "x pertence à união de A

    com B" é o mesmo que: "x pertence a A ou x pertence a B" Em matemática: x ∈ (A ∪ B) ⟺ (x ∈ A) ∨ (x ∈ B) Em Elixir: MapSet.union/2,
 Bitwise.bor/2, ||| 39
  25. DIFERENÇA "x pertence a A mas não pertence a B"

    é o mesmo que: "elementos de A menos elementos de B" Notação matemática: x ∈ (A ∖ B) ⟺ (x ∈ A) ∧ (x ∉ B) Em Elixir: MapSet.difference/2 40
  26. DIFERENÇA SIMÉTRICA "x pertence a A ou x pertence a

    B mas não pertence a ambos" é o mesmo que: "x pertence à união de A com B menos a intersecção de A com B" Em matemática: 
 Em Elixir: Bitwise.bxor/2, ^^^ 41 x ∈ (A ∆ B) ⟺ (x ∈ A) ⊻ (x ∈ B)
  27. CONJUNTOS EM VÁRIAS LINGUAGENS/PLATAFORMAS Amostra de linguagens ou APIs de

    plataformas que oferecem conjuntos em sua biblioteca-padrão. 43 Elixir MapSet: 14 métodos Ruby Set: > 10 métodos e operadores Python set, frozenset: > 10 métodos e operadores .Net (C# etc.) ISet interface: > 10 métodos; 2 implementações JavaScript (ES6) Set: < 10 métodos Java Set interface: < 10 métodos; 8 implementações Go Faça você mesmo, ou escolha um dos N pacotes...
  28. CONJUNTOS EM VÁRIAS LINGUAGENS/PLATAFORMAS Amostra de linguagens ou APIs de

    plataformas que oferecem conjuntos em sua biblioteca-padrão. 44 Elixir MapSet: 14 métodos Ruby Set: > 10 métodos e operadores Python set, frozenset: > 10 métodos e operadores .Net (C# etc.) ISet interface: > 10 métodos; 2 implementações JavaScript (ES6) Set: < 10 métodos Java Set interface: < 10 métodos; 8 implementações Go Faça você mesmo, ou escolha um dos N pacotes...
  29. INTERFACE DE MAPSET Construção 46 new() Cria um novo MapSet

    vazio. new(enum) Cria um MapSet a partir de um enumerável. new(enum, transform) Idem, aplicando função transform a cada elemento. member?(set, elemento) Testa se o elemento pertence ao MapSet. put(set, elemento) Insere o elemento. Se há membro igual, nada acontece. delete(set, elemento) Retira o elemento do MapSet. size(set) Devolve o número de elementos do MapSet. to_list(set) Cria uma lista a partir do MapSet. Operações básicas
  30. INTERFACE DE MAPSET Operações entre conjuntos — devolvem novo MapSet

    47 intersection(set1, set2) Intersecção entre dois MapSet. A ∩ B union(set1, set2) União de dois MapSet. A ∪ B difference(set1, set2) Diferença set1 ➖ set2. A ∖ B Testes — devolvem booleano member?(set, elemento) Elemento pertence ao MapSet? x ∈ A subset?(set1, set2) Todos os elementos de set1 estão em set2? A ⊆ B equal?(set1, set2) set1 e set2 tem os mesmos elementos? A = B disjoint?(set1, set2) set1 e set2 não tem elementos em comum? A ∩ B = ∅
  31. ORIGEM DA IDEIA: THE GO PROGRAMMING LANGUAGE The Go Programming

    Language Alan A. A. Donovan & Brian W. Kernighan 49
  32. INTERFACE DE UINTSET Construção — como MapSet, só para elementos

    inteiros 50 new() Cria um novo UintSet vazio. new(enum) Cria um UintSet a partir de um enumerável. new(enum, transform) Idem, aplicando função transform a cada elemento. member?(set, elemento) Testa se o elemento pertence ao UintSet. put(set, elemento) Insere o elemento. Se há membro igual, nada acontece. delete(set, elemento) Retira o elemento do UintSet. length(set) Devolve o número de elementos do UintSet — O(n). to_list(set) Cria uma lista a partir do UintSet. Operações básicas — a função diferente: size/1 ≠ length/1
  33. INTERFACE DE UINTSET Operações entre conjuntos — devolvem novo UintSet

    51 intersection(set1, set2) Intersecção entre dois UintSet. A ∩ B union(set1, set2) União de dois UintSet. A ∪ B difference(set1, set2) Diferença set1 ➖ set2. A ∖ B Testes — devolvem booleano member?(set, elemento) Elemento pertence ao UintSet? x ∈ A subset?(set1, set2) Todos os elementos de set1 estão em set2? A ⊆ B equal?(set1, set2) set1 e set2 tem os mesmos elementos? A = B disjoint?(set1, set2) set1 e set2 não tem elementos em comum? A ∩ B = ∅
  34. APRENDENDO COM CONJUNTOS Operações com conjuntos podem simplificar algoritmos. Elixir

    oferece uma implementação rica: MapSet. O código de MapSet é um excelente exemplo de abstração de dados usando struct e protocolos. A interface de UintSet é quase a mesma de MapSet,
 mas a implementação é mais simples, com operadores Bitwise para manipular inteiros como vetores de bits. 75 https://github.com/ramalho/uint_set