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

Além do else! Categorizando Pokemóns com Pattern Matching no JavaScript

Além do else! Categorizando Pokemóns com Pattern Matching no JavaScript

Nessa sessão, Willian vai destrinchar os building blocks fundamentais para árvore de decisão em JavaScript, as diferenças entre elas, a lacuna que a proposta Pattern matching tenta preencher e todos os benefícios que os desenvolvedores podem ter quando essa funcionalidade for incorporada na linguagem no futuro.

Willian Martins

April 22, 2024
Tweet

More Decks by Willian Martins

Other Decks in Technology

Transcript

  1. • Codo fofo desde 2004 • UI desde 2007 •

    Netflix - TVUI • Ex-UMA-PORRADA-DE- COISA • Podcast DNE e Lives Sobre Mim
  2. Declaração vs expressão • Expressão sempre retorna um valor •

    Pode ser tão complexa quanto o autor do código quiser. (vide expression statements) • Declaração só executa o que está dentro dela • Declarações longas podem ser delimitada por `{` e `}`
  3. Como a expressão condicional é avaliada • Faz a avaliação

    da expressão • Se a expressão resolver em Boolean, retorna o valor • Se a expressão resolver am algum desses valores: false, 0, -0, 0n, "", null, undefined, NaN, retorna false • Pra qualquer outro valor, retorna true.
  4. • Nao existe else if • O if só executa

    a próxima instrução após a declaração. • O mesmo serve pro else • Pra executar mais de uma declaração, use se as {} pra delimitar um bloco declarativo E o else if if (condição) { // Mágica aqui 🪄 } else { //…Não tem mágica 😕 }
  5. • Nao existe else if • O if só executa

    a próxima instrução após a declaração. • O mesmo serve pro else • Pra executar mais de uma declaração, use se as {} pra delimitar um bloco declarativo E o else if if (condição) { // Mágica aqui 🪄 } else if (outraCondição) { // Outra mágica🪄🐇 } else { //…Não tem mágica 😕 }
  6. • Nao existe else if • O if só executa

    a próxima instrução após a declaração. • O mesmo serve pro else • Pra executar mais de uma declaração, use se as {} pra delimitar um bloco declarativo E o else if if (condição) { // Mágica aqui 🪄 } else if (outraCondição) { // Outra mágica🪄🐇 } else { //…Não tem mágica 😕 }
  7. • Nao existe else if • O if só executa

    a próxima instrução após a declaração. • O mesmo serve pro else • Pra executar mais de uma declaração, use se as {} pra delimitar um bloco declarativo E o else if if (condição) { // Mágica aqui 🪄 } else if (outraCondição) { // Outra mágica🪄🐇 } else { //…Não tem mágica 😕 }
  8. • Nao existe else if • O if só executa

    a próxima instrução após a declaração. • O mesmo serve pro else • Pra executar mais de uma declaração, use se as {} pra delimitar um bloco declarativo E o else if if (condição) { // Mágica aqui 🪄 } else if (outraCondição) { // Outra mágica🪄🐇 } else { //…Não tem mágica 😕 }
  9. • Expressão como input A instrução switch switch(expressão) { case

    exp1: ... break; case exp2: case exp3: ... break; default: ... }
  10. • Expressão como input • Comparação com a expressão da

    clausula case A instrução switch switch(expressão) { case exp1: ... break; case exp2: case exp3: ... break; default: ... }
  11. • Expressão como input • Comparação com a expressão da

    clausula case • Ponto de entrada onde as expressões se correspondem A instrução switch switch(expressão) { case exp1: ... break; case exp2: case exp3: ... break; default: ... }
  12. • Expressão como input • Comparação com a expressão da

    clausula case • Ponto de entrada onde as expressões se correspondem A instrução switch switch(expressão) { case exp1: ... break; case exp2: case exp3: ... break; default: ... }
  13. • Expressão como input • Comparação com a expressão da

    clausula case • Ponto de entrada onde as expressões se correspondem • Clausula default pra caso a expressão não case com nada A instrução switch switch(expressão) { case exp1: ... break; case exp2: case exp3: ... break; default: ... }
  14. • Pode substituir a cadeia de if- else usando true

    como de expressão de entrada E o switch true? if (condição) { // Mágica aqui 🪄 } else if (outraCondição) { // Outra mágica 🪄🐇 } else { // Não tem mágica 😕 }
  15. • Pode substituir a cadeia de if- else usando true

    como de expressão de entrada • Expressões podem ser usadas tanto na expressão de entrada quanto na clausula case E o switch true? switch (true) { case condição: // Mágica aqui 🪄 break; case outraCondição: // Outra mágica 🪄🐇 break; default: // Não tem mágica 😕 }
  16. Qual é o resultado? switch (true) { case '1': console.info('uno');

    break; case 1: console.info('numero'); break; case false: console.info('falso'); break; default: console.info('oche'); }
  17. Qual é o resultado? switch (true) { case '1': console.info('uno');

    break; case 1: console.info('numero'); break; case false: console.info('falso'); break; default: console.info('oche'); }
  18. • Única expressão condicional do JS • Unico operador ternário

    da linguagem • Os tres operandos são expressões Operador ternário expression ? expIfTrue : expIfFalse;
  19. • Única expressão condicional do JS • Unico operador ternário

    da linguagem • Os tres operandos são expressões Operador ternário expression ? expIfTrue : expIfFalse;
  20. • Única expressão condicional do JS • Unico operador ternário

    da linguagem • Os tres operandos são expressões Operador ternário expression ? expIfTrue : expIfFalse;
  21. • Única expressão condicional do JS • Unico operador ternário

    da linguagem • Os tres operandos são expressões Operador ternário expression ? expIfTrue : expIfFalse;
  22. • Única expressão condicional do JS • Unico operador ternário

    da linguagem • Os tres operandos são expressões Operador ternário if (condição) { // Mágica aqui 🪄 } else if (outraCondição) { // Outra mágica🪄🐇 } else { //…Não tem mágica 😕 }
  23. condição ? magica // Mágica aqui 🪄 : outraCondição ?

    outraMagica // Outra mágica 🪄🐇 : semMagica // Não tem mágica 😕
  24. condição ? magica // Mágica aqui 🪄 : outraCondição ?

    outraMagica // Outra mágica 🪄🐇 : semMagica // Não tem mágica 😕
  25. Problema exemplo • Tenho um , um e um .

    • Se eu achar um pokemon do tipo: • Grama ou Inseto -> uso • Terra ou Agua -> uso • Fogo ou Pedra -> uso • Caso contrario -> Fuja
  26. const whatPokemon = enemy => { if (enemy.type[0] === 'Grama'

    || enemy.type[1] === 'Grama') { return 'Charmander'; } if (enemy.type[0] === 'Inseto' || enemy.type[1] === 'Inseto') { return 'Charmander'; } if (enemy.type[0] === 'Terra' || enemy.type[1] === 'Terra') { return 'Bulbasaur'; } if (enemy.type[0] === 'Agua' || enemy.type[1] === 'Agua') { return 'Bulbasaur'; } if (enemy.type[0] === 'Fogo' || enemy.type[1] === 'Fogo') { return 'Squirtle'; } if (enemy.type[0] === 'Pedra' || enemy.type[1] === 'Pedra') { return 'Squirtle'; } return "Fuja"; }
  27. const whatPokemon = (enemy) => { if (['Grama', 'Inseto'].includes(enemy.type[0]) ||

    ['Grama', 'Inseto'].includes(enemy.type[1])) { return 'Charmander'; } if (['Terra', 'Agua'].includes(enemy.type[0]) || ['Terra', 'Agua'].includes(enemy.type[1])) { return 'Bulbasaur'; } if (['Fogo', 'Pedra'].includes(enemy.type[0]) || ['Fogo', 'Pedra'].includes(enemy.type[1])) { return 'Squirtle'; } return "Fuja"; }
  28. const whatPokemon = enemy => { switch (true) { case

    enemy.type[0] === 'Grama': case enemy.type[1] === 'Grama': case enemy.type[0] === 'Inseto': case enemy.type[1] === 'Inseto': return 'Charmander'; case enemy.type[0] === 'Terra': case enemy.type[1] === 'Terra': case enemy.type[0] === 'Agua': case enemy.type[1] === 'Agua': return 'Bulbasaur'; case enemy.type[0] === 'Fogo': case enemy.type[1] === 'Fogo': case enemy.type[0] === 'Pedra': case enemy.type[1] === 'Pedra': return 'Squirtle'; default: return 'Fuja'; } }
  29. const whatPokemon = enemy => { switch (true) { case

    ['Grama', ‘Inseto’].includes(enemy.type[0] || ['Grama', 'Inseto'].includes(enemy.type[1]): return 'Charmander'; case ['Terra', ‘Agua’].includes(enemy.type[0]) || ['Terra', ‘Agua'].includes(enemy.type[1]): return 'Bulbasaur'; case ['Fogo', ‘Pedra'].includes(enemy.type[0]) || ['Fogo', 'Pedra'].includes(enemy.type[1]): return 'Squirtle'; default: return "Fuja"; } }
  30. const whatPokemon = enemy => ['Grama', ‘Inseto'].includes(enemy.type[0]) || ['Grama', 'Inseto'].includes(enemy.type[1])

    ? 'Charmander' : ['Terra', 'Agua'].includes(enemy.type[0]) || ['Terra', 'Agua'].includes(enemy.type[1]) ? 'Bulbasaur' : ['Fogo', 'Pedra'].includes(enemy.type[0]) || ['Fogo', 'Pedra'].includes(enemy.type[1]) ? 'Squirtle' : "Fuja";
  31. • Expressão • Recebe um subject pra teste • Tenta

    casar com o pattern de cada clausula when • Quando casa, retorna o valor da expressão da clausula when • Se nada casa, retorna a expressão da clausula default Instrução match match(<subject-expression>) { when <pattern>: <value-expression>; ... default: <value-expression>; }
  32. const whatPokemon = enemy => match (enemy.type) { when ["Grama",...]

    or [,"Grama"]: 'Charmander'; default: 'Fuja'; }
  33. const whatPokemon = enemy => match (enemy.type) { when ["Grama",

    ...] or [,"Grama"]: 'Charmander'; when ["Inseto", ...] or [,"Inseto"]: 'Charmander'; default: 'Fuja'; }
  34. const whatPokemon = enemy => match (enemy.type) { when [/Grama|Inseto/,

    ...] or [,/Grama|Inseto/]: 'Charmander'; when [/Terra|Agua/, ...] or [,/Terra|Agua/]: 'Bulbasaur'; when [/Fogo|Pedra/, ...] or [,/Fogo|Pedra/]: 'Squirtle'; default: 'Fuja'; }
  35. const whatPokemon = enemy => match (enemy.type) { when ['Grama'

    or 'Inseto', ...] or [,'Grama' or 'Inseto']: 'Charmander'; when ['Terra' or 'Agua', ...] or [,'Terra' or 'Agua']: 'Bulbasaur'; when ['Fogo' or 'Pedra', ...] or [,'Fogo' or 'Pedra']: 'Squirtle'; default: 'Fuja'; }
  36. const Pokemon = { BomPraCharmander: { [Symbol.customMatcher](subject) { return ["Grama",

    “Inseto"].includes(subject[0]) || ["Grama", "Inseto"].includes(subject[1]); } }, };
  37. const Pokemon = { BomPraCharmander: { [Symbol.customMatcher](subject) { return ["Grama",

    “Inseto"].includes(subject[0]) || ["Grama", "Inseto"].includes(subject[1]); } }, BomPraBulbasaur: { [Symbol.customMatcher](subject) { return ["Terra", “Agua"].includes(subject[0]) || ["Terra", "Agua"].includes(subject[1]); } }, BomPraSquirtle: { [Symbol.customMatcher](subject) { return ["Fogo", “Pedra"].includes(subject[0]) || ["Fogo", "Pedra"].includes(subject[1]); } } };
  38. const whatPokemon = enemy => match (enemy.type) { when Pokemon.BomPraCharmander:

    'Charmander'; when Pokemon.BomPraBulbasaur: 'Bulbasaur'; when Pokemon.BomPraSquirtle: 'Squirtle'; default: 'Fuja'; }
  39. • Operador binário • Primeiro operando é o subject •

    Segundo operando é o pattern • Resolve a expressão em booleano Operador is <subject-expression> is <pattern>;
  40. Conclusão • JS tem vários tipos de condicionais • Switch

    tem a estrutura mas falta expressividade • If tem a expressividade mas falta estrutura • Condicional ternário é a única condicional que é expressão • Pattern match cobre as limitações das expressões anteriores • Custom matcher e o operador is expande a expressividade de condicionaos no JS
  41. Fim