DEV Community

Matheus de Camargo Marques
Matheus de Camargo Marques

Posted on

Elixir Enchiridium — Tomo IV: A Sintaxe parte 2

AVISO: esta série é uma fantasia satírica baseada em fatos reais sobre Elixir. Nada aqui deve ser levado ao pé da letra. Ao final de cada capítulo, os fatos por trás da lenda são revelados. Tags: #satire #humor #elixir #enchiridium


Elixir Enchiridium — Tomo IV: A Sintaxe

Capítulos 11 a 40


Capítulo 11 — try/rescue: A Rede de Segurança que Ninguém Quer Usar

A lenda diz que o try/rescue é uma rede de segurança. Você estende a rede. Se você cair, a rede te pega. Se não cair, a rede fica lá, esperando. Mas os programadores Elixir não gostam da rede. Eles preferem cair. Eles preferem o "let it crash". A rede é para os fracos.

A verdade é que try/rescue é uma construção que permite capturar exceções. try executa um bloco de código; rescue captura exceções; after executa código independentemente de ter havido exceção ou não. No entanto, a comunidade Elixir geralmente prefere usar case com tuplas {:ok, _} e {:error, _} em vez de exceções para fluxos esperados. Exceções são reservadas para erros verdadeiramente excepcionais.

A lenda diz que, na primeira vez que um programador usou try/rescue, ele perguntou: "Por que ninguém usa isso?" O instrutor respondeu: "Porque ninguém quer cair." O programador perguntou: "E se eu cair?" O instrutor respondeu: "Aí o supervisor te pega."

O fato por trás da lenda: try/rescue permite capturar exceções com try, rescue, after e else. A comunidade Elixir prefere usar case com tuplas {:ok, _} e {:error, _} para fluxos esperados, reservando exceções para erros excepcionais.

Gancho: A rede de segurança existe. Mas há uma coisa que simplifica as condições: o cond.


Capítulo 12 — cond: A Escada de Condições que Nunca Para

A lenda diz que o cond é uma escada. Cada degrau é uma condição. Você sobe a escada até encontrar um degrau verdadeiro. Se nenhum for verdadeiro, o CondClauseError aparece. A escada nunca para. A escada nunca mente.

A verdade é que cond é uma expressão que avalia uma série de condições e executa o corpo da primeira que for verdadeira. Se nenhuma for verdadeira, uma exceção CondClauseError é levantada. cond é útil quando você tem múltiplas condições que não se encaixam bem em um case (porque não são padrões, são expressões booleanas). A cláusula final geralmente é true -> para capturar todos os casos.

A lenda diz que, na primeira vez que um programador usou cond, ele perguntou: "E se nenhuma condição for verdadeira?" O instrutor respondeu: "Aí você chora." O programador perguntou: "Posso adicionar um true?" O instrutor respondeu: "Pode. E deve."

O fato por trás da lenda: cond avalia uma série de condições e executa o corpo da primeira que for verdadeira. Se nenhuma for verdadeira, uma exceção CondClauseError é levantada. A cláusula final geralmente é true -> para capturar todos os casos.

Gancho: A escada sobe. Mas há uma coisa que percorre listas: as compreensões.


Capítulo 13 — Compreensões: A Fábrica que Transforma Listas

A lenda diz que as compreensões são fábricas. Você coloca uma lista de entrada, uma ou mais expressões de filtro, e uma expressão de saída. A fábrica processa cada elemento. Se o elemento passa no filtro, ele é transformado. Se não passa, é descartado. A fábrica nunca para. A fábrica nunca erra.

A verdade é que compreensões em Elixir (for) permitem gerar listas, mapas e streams a partir de enumeráveis. A sintaxe é for x <- enumerable, filter, do: expression. Você pode ter múltiplos geradores e múltiplos filtros. Compreensões são uma forma concisa de expressar operações de mapeamento e filtragem.

A lenda diz que, na primeira vez que um programador usou for, ele perguntou: "Isso é um loop?" O instrutor respondeu: "Não. É uma compreensão." O programador perguntou: "Qual a diferença?" O instrutor respondeu: "Compreensão não é imperativa. É funcional."

O fato por trás da lenda: Compreensões em Elixir (for) permitem gerar listas, mapas e streams a partir de enumeráveis. A sintaxe é for x <- enumerable, filter, do: expression. Você pode ter múltiplos geradores e filtros.

Gancho: A fábrica transforma. Mas há uma coisa que representa bytes: os binários.


Capítulo 14 — Binários e Bitstrings: A Fábrica de Bits

A lenda diz que os binários são fábricas de bits. Um binário é uma sequência de bytes. Um bitstring é uma sequência de bits. Você pode construir, destruir, dividir e combinar. A fábrica de bits nunca para. A fábrica de bits nunca erra.

A verdade é que binários e bitstrings em Elixir são sequências de bytes e bits. A sintaxe <<>> permite construir e fazer pattern matching em binários. Você pode especificar o tamanho, o tipo (integer, float, binary, utf8, etc.) e a unidade. Binários são usados para protocolos de rede, processamento de imagens, criptografia e muito mais.

A lenda diz que, na primeira vez que um programador usou <<>>, ele perguntou: "Isso é uma string?" O instrutor respondeu: "Não. É um binário." O programador perguntou: "E a string?" O instrutor respondeu: "String é um binário UTF-8."

O fato por trás da lenda: Binários e bitstrings em Elixir são sequências de bytes e bits. A sintaxe <<>> permite construir e fazer pattern matching em binários, com especificações de tamanho, tipo e unidade.

Gancho: Os binários representam. Mas há uma coisa que representa texto: as strings.


Capítulo 15 — Strings: A Sequência de Bytes que Fala UTF-8

A lenda diz que as strings são sequências de bytes. Mas não são bytes quaisquer. São bytes UTF-8. Elas falam a língua dos humanos. Elas guardam acentos, emojis e ideogramas. As strings são gentis. As strings são poderosas.

A verdade é que strings em Elixir são binários codificados em UTF-8. O módulo String fornece funções para manipular strings: String.length/1, String.upcase/1, String.split/2, String.replace/3, e muitas outras. Strings são representadas com aspas duplas ("), enquanto charlists são representadas com aspas simples (').

A lenda diz que, na primeira vez que um programador usou String.length/1, ele perguntou: "Por que não é .length?" O instrutor respondeu: "Porque string é um binário. E binários não têm métodos." O programador perguntou: "E o .?" O instrutor respondeu: "O . é para módulos."

O fato por trás da lenda: Strings em Elixir são binários codificados em UTF-8. O módulo String fornece funções para manipulação. Strings são representadas com aspas duplas, charlists com aspas simples.

Gancho: As strings falam. Mas há uma coisa que guarda sequências: as listas.


Capítulo 16 — Listas: A Corrente que Nunca se Rompe

A lenda diz que as listas são correntes. Cada elo é um elemento. Cada elo aponta para o próximo. Você pode adicionar um elo no início. Você pode remover um elo do início. Mas você não pode adicionar no fim sem percorrer toda a corrente. As listas são eficientes no início. As listas são teimosas no fim.

A verdade é que listas em Elixir são listas ligadas. Cada elemento aponta para o próximo. Adicionar ou remover do início é O(1). Adicionar ou remover do fim é O(n). Listas são usadas para armazenar sequências de elementos. O módulo List fornece funções como List.first/1, List.last/1, List.flatten/1, e muitas outras.

A lenda diz que, na primeira vez que um programador tentou adicionar no fim, ele perguntou: "Por que é lento?" O instrutor respondeu: "Porque a corrente não sabe onde termina." O programador perguntou: "E no início?" O instrutor respondeu: "No início é rápido. O início sabe onde começa."

O fato por trás da lenda: Listas em Elixir são listas ligadas. Adicionar ou remover do início é O(1); do fim é O(n). O módulo List fornece funções para manipulação.

Gancho: As listas guardam. Mas há uma coisa que guarda pares: as tuplas.


Capítulo 17 — Tuplas: Os Pares que Nunca Mudam

A lenda diz que as tuplas são pares. Elas guardam dois, três, quatro elementos. Mas elas nunca mudam. Uma tupla é imutável. Uma tupla é eterna. Se você quer mudar uma tupla, você cria outra. As tuplas são honestas. As tuplas são previsíveis.

A verdade é que tuplas em Elixir são coleções ordenadas de elementos, representadas com chaves ({}). Tuplas são imutáveis e acessadas por índice. O módulo Tuple fornece funções como Tuple.append/2, Tuple.delete_at/2, Tuple.insert_at/3, e muitas outras. Tuplas são frequentemente usadas para retornar múltiplos valores de uma função, como {:ok, result} e {:error, reason}.

A lenda diz que, na primeira vez que um programador usou uma tupla, ele perguntou: "Por que não posso mudar?" O instrutor respondeu: "Porque tuplas são eternas." O programador perguntou: "E se eu precisar mudar?" O instrutor respondeu: "Aí você cria outra."

O fato por trás da lenda: Tuplas em Elixir são coleções ordenadas e imutáveis, representadas com {}. O módulo Tuple fornece funções para manipulação. Tuplas são usadas para retornar múltiplos valores, como {:ok, result} e {:error, reason}.

Gancho: As tuplas guardam. Mas há uma coisa que guarda chaves e valores: os mapas.


Capítulo 18 — Mapas: A Tabela que Nunca se Confunde

A lenda diz que os mapas são tabelas. Cada chave aponta para um valor. Cada valor é encontrado pela chave. Os mapas são eficientes. Os mapas são flexíveis. Os mapas nunca se confundem. Se você tentar acessar uma chave que não existe, o mapa te dá nil.

A verdade é que mapas em Elixir são coleções de pares chave-valor, representadas com %{}. Mapas são imutáveis e acessados por chave. O módulo Map fornece funções como Map.get/3, Map.put/3, Map.delete/2, Map.merge/2, e muitas outras. Mapas são usados para armazenar dados estruturados e configurações.

A lenda diz que, na primeira vez que um programador usou um mapa, ele perguntou: "Por que não é um objeto?" O instrutor respondeu: "Porque não precisa ser." O programador perguntou: "E se eu precisar de métodos?" O instrutor respondeu: "Aí você usa módulos."

O fato por trás da lenda: Mapas em Elixir são coleções de pares chave-valor, representadas com %{}. O módulo Map fornece funções para manipulação. Mapas são usados para armazenar dados estruturados e configurações.

Gancho: Os mapas guardam. Mas há uma coisa que guarda valores únicos: os Keyword Lists.


Capítulo 19 — Keyword Lists: A Lista que Guarda Opções

A lenda diz que as keyword lists são listas de opções. Cada opção é um par {chave, valor}. Elas são usadas para passar opções para funções. Elas são ordenadas. Elas permitem chaves duplicadas. Elas são a forma mais antiga de passar opções em Elixir.

A verdade é que keyword lists são listas de tuplas de dois elementos, onde o primeiro é um átomo. Elas são frequentemente usadas para passar opções para funções, como String.split("a,b,c", ",", trim: true). Keyword lists são ordenadas e permitem chaves duplicadas (a primeira ocorrência é usada por funções como Keyword.get/3).

A lenda diz que, na primeira vez que um programador usou uma keyword list, ele perguntou: "Por que não um mapa?" O instrutor respondeu: "Porque keyword lists são ordenadas." O programador perguntou: "E se eu precisar de ordem?" O instrutor respondeu: "Aí você usa keyword list."

O fato por trás da lenda: Keyword lists são listas de tuplas {átomo, valor}. Elas são ordenadas, permitem chaves duplicadas, e são usadas para passar opções para funções.

Gancho: As keyword lists guardam. Mas há uma coisa que guarda nomes: os átomos.


Capítulo 20 — Átomos: Os Nomes que Nunca Morrem

A lenda diz que os átomos são nomes. Eles começam com :. Eles são únicos. Eles são eternos. Eles nunca são coletados pelo garbage collector. Se você criar um átomo, ele vive para sempre. Os átomos são poderosos. Os átomos são perigosos.

A verdade é que átomos em Elixir são constantes nomeadas, representadas com :nome. Eles são únicos e armazenados em uma tabela global. Átomos não são coletados pelo garbage collector, o que significa que criar muitos átomos dinamicamente pode esgotar a memória. Átomos são frequentemente usados como chaves em keyword lists e mapas, e como nomes de módulos e funções.

A lenda diz que, na primeira vez que um programador criou um átomo dinamicamente, ele perguntou: "Posso criar quantos?" O instrutor respondeu: "Pode. Mas cuidado." O programador perguntou: "Por quê?" O instrutor respondeu: "Porque átomos nunca morrem."

O fato por trás da lenda: Átomos em Elixir são constantes nomeadas, representadas com :nome. Eles são únicos e não são coletados pelo garbage collector. Criar muitos átomos dinamicamente pode esgotar a memória.

Gancho: Os átomos nomeiam. Mas há uma coisa que converte: o String.to_atom/1.


Capítulo 21 — O Perigo do String.to_atom/1: O Feitiço que Cria Monstros

A lenda diz que o String.to_atom/1 é um feitiço perigoso. Ele converte uma string em um átomo. Mas cada átomo criado vive para sempre. Se você converter strings de entrada do usuário, você cria átomos sem parar. A memória acaba. A BEAM chora. O sistema cai.

A verdade é que String.to_atom/1 cria um átomo a partir de uma string. Como átomos não são coletados pelo garbage collector, converter strings arbitrárias (especialmente de entrada do usuário) pode levar a um vazamento de memória. A alternativa segura é String.to_existing_atom/1, que só converte se o átomo já existir.

A lenda diz que, na primeira vez que um programador usou String.to_atom/1, ele perguntou: "Qual o problema?" O instrutor respondeu: "Cada átomo é eterno." O programador perguntou: "E se eu criar um milhão?" O instrutor respondeu: "Aí você tem um milhão de átomos eternos."

O fato por trás da lenda: String.to_atom/1 cria um átomo a partir de uma string. Como átomos não são coletados, converter strings arbitrárias pode causar vazamento de memória. String.to_existing_atom/1 é a alternativa segura.

Gancho: Os átomos são perigosos. Mas há uma coisa que converte sem perigo: o Integer.parse/1.


Capítulo 22 — Números: Inteiros, Floats e a Matemática que Nunca Erra

A lenda diz que os números em Elixir são de dois tipos: inteiros e floats. Inteiros são precisos. Floats são aproximados. Inteiros podem ser arbitrariamente grandes. Floats têm precisão limitada. A matemática nunca erra. Mas os floats às vezes mentem.

A verdade é que Elixir tem inteiros (arbitrariamente grandes) e floats (ponto flutuante de precisão dupla). Inteiros são precisos; floats são aproximados. O módulo Integer fornece funções como Integer.parse/1, Integer.to_string/1, Integer.gcd/2. O módulo Float fornece funções como Float.round/2, Float.ceil/1, Float.floor/1.

A lenda diz que, na primeira vez que um programador somou 0.1 + 0.2, ele perguntou: "Por que não é 0.3?" O instrutor respondeu: "Porque floats são aproximados." O programador perguntou: "E inteiros?" O instrutor respondeu: "Inteiros são precisos. Use inteiros quando puder."

O fato por trás da lenda: Elixir tem inteiros (arbitrariamente grandes) e floats (precisão dupla). Inteiros são precisos; floats são aproximados. Integer e Float fornecem funções de manipulação.

Gancho: Os números calculam. Mas há uma coisa que calcula com precisão: o módulo Decimal.


Capítulo 23 — Decimal: A Matemática que Não Mente

A lenda diz que o Decimal é a matemática que não mente. Ele não usa floats. Ele usa precisão arbitrária. Ele é usado em finanças. Ele é usado em ciência. Ele nunca erra. Ele nunca aproxima.

A verdade é que Decimal é uma biblioteca que fornece aritmética decimal de precisão arbitrária. Ela é usada quando floats não são suficientes, como em cálculos financeiros. Decimal implementa as operações aritméticas básicas e funções como Decimal.round/2, Decimal.compare/2, Decimal.to_string/1.

A lenda diz que, na primeira vez que um programador usou Decimal, ele perguntou: "Por que não usar float?" O instrutor respondeu: "Porque float mente." O programador perguntou: "E Decimal?" O instrutor respondeu: "Decimal não mente. Decimal é honesto."

O fato por trás da lenda: Decimal é uma biblioteca que fornece aritmética decimal de precisão arbitrária, usada em cálculos financeiros e científicos onde floats não são suficientes.

Gancho: O Decimal calcula. Mas há uma coisa que enumera: o protocolo Enumerable.


Capítulo 24 — Enumerable: O Protocolo que Tudo Percorre

A lenda diz que o Enumerable é um protocolo. Ele é implementado por listas, mapas, ranges, streams e muitas outras estruturas. Ele permite percorrer, mapear, filtrar, reduzir. O Enumerable nunca para. O Enumerable nunca erra.

A verdade é que Enumerable é um protocolo implementado por todas as estruturas que podem ser enumeradas. Ele fornece funções como Enum.map/2, Enum.filter/2, Enum.reduce/3, Enum.each/2, e muitas outras. Listas, mapas, ranges, streams e outras estruturas implementam Enumerable.

A lenda diz que, na primeira vez que um programador usou Enum.map/2, ele perguntou: "Isso é um loop?" O instrutor respondeu: "Não. É uma enumeração." O programador perguntou: "Qual a diferença?" O instrutor respondeu: "Enumeração é funcional. Loop é imperativo."

O fato por trás da lenda: Enumerable é um protocolo implementado por listas, mapas, ranges, streams e outras estruturas. Ele fornece Enum.map/2, Enum.filter/2, Enum.reduce/3, Enum.each/2, e muitas outras funções.

Gancho: O Enumerable percorre. Mas há uma coisa que transforma sem percorrer: o Stream.


Capítulo 25 — Stream: A Enumeração que Não Enumera (Até Precisar)

A lenda diz que o Stream é uma enumeração preguiçosa. Ele não faz nada até você pedir. Ele não percorre. Ele não transforma. Ele espera. Quando você pede, ele faz. Quando você não pede, ele não faz. O Stream é paciente. O Stream é eficiente.

A verdade é que Stream é um módulo para criar enumerações preguiçosas. Diferente de Enum, que avalia tudo imediatamente, Stream cria uma sequência de operações que só são executadas quando necessário. Isso é útil para processar grandes coleções ou streams infinitos. Stream.map/2, Stream.filter/2, Stream.take/2 são algumas das funções.

A lenda diz que, na primeira vez que um programador usou Stream, ele perguntou: "Por que não faz nada?" O instrutor respondeu: "Porque é preguiçoso." O programador perguntou: "E quando faz?" O instrutor respondeu: "Quando você pede."

O fato por trás da lenda: Stream é um módulo para criar enumerações preguiçosas. Diferente de Enum, que avalia tudo imediatamente, Stream cria uma sequência de operações que só são executadas quando necessário.

Gancho: O Stream espera. Mas há uma coisa que transforma listas: o Enum.


Capítulo 26 — Enum: A Fábrica que Transforma Tudo

A lenda diz que o Enum é uma fábrica. Ele pega uma coleção e a transforma. Ele mapeia. Ele filtra. Ele reduz. Ele ordena. Ele agrupa. O Enum nunca para. O Enum nunca erra.

A verdade é que Enum é um módulo que fornece funções para trabalhar com coleções enumeráveis. Enum.map/2 transforma cada elemento. Enum.filter/2 filtra elementos. Enum.reduce/3 reduz a coleção a um único valor. Enum.sort/1 ordena. Enum.group_by/2 agrupa. Enum é uma das ferramentas mais usadas em Elixir.

A lenda diz que, na primeira vez que um programador usou Enum.reduce/3, ele perguntou: "O que é reduzir?" O instrutor respondeu: "É transformar uma coleção em um valor." O programador perguntou: "Como?" O instrutor respondeu: "Com um acumulador."

O fato por trás da lenda: Enum fornece funções para trabalhar com coleções enumeráveis: Enum.map/2, Enum.filter/2, Enum.reduce/3, Enum.sort/1, Enum.group_by/2, e muitas outras.

Gancho: O Enum transforma. Mas há uma coisa que transforma com padrões: o for.


Capítulo 27 — Compreensões (Parte 2): A Fábrica que Filtra e Transforma

A lenda diz que as compreensões são fábricas que filtram e transformam. Você coloca uma lista. Você adiciona filtros. Você adiciona transformações. A fábrica faz o resto. As compreensões são concisas. As compreensões são poderosas.

A verdade é que compreensões em Elixir (for) permitem gerar listas, mapas e streams a partir de enumeráveis. A sintaxe é for x <- enumerable, filter, do: expression. Você pode ter múltiplos geradores e múltiplos filtros. Compreensões são uma forma concisa de expressar operações de mapeamento e filtragem.

A lenda diz que, na primeira vez que um programador usou for com dois geradores, ele perguntou: "Isso é um loop aninhado?" O instrutor respondeu: "Não. É uma compreensão com dois geradores." O programador perguntou: "Qual a diferença?" O instrutor respondeu: "Compreensão é funcional. Loop é imperativo."

O fato por trás da lenda: Compreensões em Elixir (for) permitem gerar listas, mapas e streams a partir de enumeráveis. Você pode ter múltiplos geradores e filtros.

Gancho: As compreensões filtram. Mas há uma coisa que filtra com padrões: o case.


Capítulo 28 — case (Parte 2): O Tribunal que Julga Cada Valor

A lenda diz que o case é um tribunal. Ele pega um valor e o julga. Cada cláusula é uma sentença. Se o valor casar com a cláusula, a sentença é executada. Se não casar com nenhuma, o CaseClauseError aparece. O tribunal é justo. O tribunal é imparcial.

A verdade é que case é uma expressão que permite comparar um valor com vários padrões. Cada cláusula tem um padrão e um corpo. O primeiro padrão que casar é executado. Se nenhum casar, uma exceção CaseClauseError é levantada.

A lenda diz que, na primeira vez que um programador usou case, ele perguntou: "Isso é um switch?" O instrutor respondeu: "Não. É um case." O programador perguntou: "Qual a diferença?" O instrutor respondeu: "switch não tem pattern matching."

O fato por trás da lenda: case permite comparar um valor com vários padrões. A primeira cláusula que casar é executada. Se nenhuma casar, uma exceção CaseClauseError é levantada.

Gancho: O case julga. Mas há uma coisa que captura erros: o try/rescue.


Capítulo 29 — try/rescue (Parte 2): A Rede de Segurança que Ninguém Quer Usar

A lenda diz que o try/rescue é uma rede de segurança. Você estende a rede. Se você cair, a rede te pega. Se não cair, a rede fica lá, esperando.

A verdade é que try/rescue é uma construção que permite capturar exceções. try executa um bloco de código; rescue captura exceções; after executa código independentemente de ter havido exceção ou não.

A lenda diz que, na primeira vez que um programador usou try/rescue, ele perguntou: "Por que ninguém usa isso?" O instrutor respondeu: "Porque ninguém quer cair." O programador perguntou: "E se eu cair?" O instrutor respondeu: "Aí o supervisor te pega."

O fato por trás da lenda: try/rescue permite capturar exceções com try, rescue, after e else. A comunidade Elixir prefere usar case com tuplas {:ok, _} e {:error, _} para fluxos esperados.

Gancho: A rede de segurança existe. Mas há uma coisa que simplifica as condições: o cond.


Capítulo 30 — cond (Parte 2): A Escada de Condições que Nunca Para

A lenda diz que o cond é uma escada. Cada degrau é uma condição. Você sobe a escada até encontrar um degrau verdadeiro. Se nenhum for verdadeiro, o CondClauseError aparece.

A verdade é que cond é uma expressão que avalia uma série de condições e executa o corpo da primeira que for verdadeira. Se nenhuma for verdadeira, uma exceção CondClauseError é levantada. A cláusula final geralmente é true -> para capturar todos os casos.

A lenda diz que, na primeira vez que um programador usou cond, ele perguntou: "E se nenhuma condição for verdadeira?" O instrutor respondeu: "Aí você chora." O programador perguntou: "Posso adicionar um true?" O instrutor respondeu: "Pode. E deve."

O fato por trás da lenda: cond avalia uma série de condições e executa o corpo da primeira que for verdadeira. Se nenhuma for verdadeira, uma exceção CondClauseError é levantada.

Gancho: A escada sobe. Mas há uma coisa que percorre listas: as compreensões.


Capítulo 31 — with (Parte 2): A Special Form que Simplifica o Fluxo

A lenda diz que o with é um feitiço. Ele pega várias expressões, e só continua se todas elas casarem. Se uma falhar, o else aparece.

A verdade é que with é uma special form do Elixir (Kernel.SpecialForms.with/1). Ele permite encadear várias expressões com pattern matching. Cada expressão é avaliada em ordem; se uma falhar, o else (se presente) é executado.

A lenda diz que, na primeira vez que um programador usou with, ele perguntou: "Isso substitui case?" O instrutor respondeu: "Não. Substitui case aninhado."

O fato por trás da lenda: with é uma special form (Kernel.SpecialForms.with/1). Ele permite encadear expressões com pattern matching, executando o else se alguma falhar.

Gancho: O with simplifica. Mas há uma coisa que explica: o case.


Capítulo 32 — Guards (Parte 2): Os Guardiões que Só Deixam Passar o Que Merece

A lenda diz que os guards são guardiões. Eles ficam na porta das funções. Quando um argumento chega, o guardião olha para ele e decide: "Você pode entrar" ou "Você não pode entrar."

A verdade é que guards são uma forma de aumentar o pattern matching com verificações mais complexas. Eles começam com a palavra-chave when, seguida de uma expressão booleana. Guards suportam operadores de comparação, booleanos estritos, e funções de verificação de tipo.

A lenda diz que, na primeira vez que um programador usou when, ele perguntou: "O que posso colocar aqui?" O instrutor respondeu: "Só o que o guardião entende."

O fato por trás da lenda: Guards começam com when e são seguidos de uma expressão booleana. Eles suportam operadores de comparação, booleanos estritos, e funções de verificação de tipo.

Gancho: Os guardiões protegem. Mas há uma coisa que organiza dados: os structs.


Capítulo 33 — Structs (Parte 2): As Fichas que Guardam Dados

A lenda diz que os structs são fichas. Cada ficha tem um formato. Cada ficha guarda dados.

A verdade é que structs são mapas com um campo especial __struct__ que define o tipo. Eles são usados para representar dados estruturados, como um usuário, um pedido ou uma configuração.

A lenda diz que, na primeira vez que um programador criou um struct, ele perguntou: "Isso é uma classe?" O instrutor respondeu: "Não. É um struct." O programador perguntou: "Qual a diferença?" O instrutor respondeu: "Struct não tem métodos."

O fato por trás da lenda: Structs são mapas com um campo __struct__ que define o tipo. Eles são usados para representar dados estruturados.

Gancho: Structs guardam. Mas há uma coisa que traduz: os protocols.


Capítulo 34 — Protocols (Parte 2): Os Tradutores que Nunca se Confundem

A lenda diz que os protocols são tradutores. Eles olham para a ficha e decidem como traduzi-la. Se a ficha é um User, o protocolo a traduz de um jeito. Se é um Post, traduz de outro.

A verdade é que protocols são mecanismos de polimorfismo que permitem despachar com base no tipo do primeiro argumento. O @derive permite derivar implementações de protocolos para structs.

A lenda diz que, na primeira vez que um programador usou um protocolo, ele perguntou: "Isso é uma interface?" O instrutor respondeu: "Não. É um protocolo." O programador perguntou: "Qual a diferença?" O instrutor respondeu: "Protocolo é mais flexível."

O fato por trás da lenda: Protocols permitem polimorfismo por despacho no tipo do primeiro argumento. @derive deriva implementações para structs.

Gancho: Protocols traduzem. Mas há uma coisa que cria strings: os sigils.


Capítulo 35 — Sigils (Parte 2): A Magia da Tilde

A lenda diz que os sigils são feitiços que começam com ~. O ~r cria uma expressão regular. O ~c cria uma charlist. O ~s cria uma string. O ~w cria uma lista de palavras.

A verdade é que sigils começam com o caractere til (~), seguido de uma letra e um delimitador. Você também pode criar sigils personalizados definindo uma função sigil_*.

A lenda diz que, na primeira vez que um programador usou ~r, ele perguntou: "Isso é regex?" O instrutor respondeu: "Sim." O programador perguntou: "E o ~?" O instrutor respondeu: "É magia."

O fato por trás da lenda: Sigils começam com ~, seguido de uma letra e um delimitador. ~r cria regex, ~c cria charlists, ~s cria strings, ~w cria listas de palavras.

Gancho: Os sigils criam. Mas há uma coisa que simplifica: o with.


Capítulo 36 — for (Parte 3): A Fábrica que Filtra e Transforma

A lenda diz que as compreensões são fábricas que filtram e transformam. Você coloca uma lista. Você adiciona filtros. Você adiciona transformações. A fábrica faz o resto.

A verdade é que compreensões em Elixir (for) permitem gerar listas, mapas e streams a partir de enumeráveis. A sintaxe é for x <- enumerable, filter, do: expression.

A lenda diz que, na primeira vez que um programador usou for com dois geradores, ele perguntou: "Isso é um loop aninhado?" O instrutor respondeu: "Não. É uma compreensão com dois geradores."

O fato por trás da lenda: Compreensões em Elixir (for) permitem gerar listas, mapas e streams a partir de enumeráveis. Você pode ter múltiplos geradores e filtros.

Gancho: As compreensões filtram. Mas há uma coisa que filtra com padrões: o case.


Capítulo 37 — case (Parte 3): O Tribunal que Julga Cada Valor

A lenda diz que o case é um tribunal. Ele pega um valor e o julga. Cada cláusula é uma sentença. Se o valor casar com a cláusula, a sentença é executada. Se não casar com nenhuma, o CaseClauseError aparece.

A verdade é que case é uma expressão que permite comparar um valor com vários padrões. Cada cláusula tem um padrão e um corpo. O primeiro padrão que casar é executado.

A lenda diz que, na primeira vez que um programador usou case, ele perguntou: "Isso é um switch?" O instrutor respondeu: "Não. É um case."

O fato por trás da lenda: case permite comparar um valor com vários padrões. A primeira cláusula que casar é executada. Se nenhuma casar, uma exceção CaseClauseError é levantada.

Gancho: O case julga. Mas há uma coisa que captura erros: o try/rescue.


Capítulo 38 — try/rescue (Parte 3): A Rede de Segurança que Ninguém Quer Usar

A lenda diz que o try/rescue é uma rede de segurança. Você estende a rede. Se você cair, a rede te pega. Se não cair, a rede fica lá, esperando.

A verdade é que try/rescue é uma construção que permite capturar exceções. try executa um bloco de código; rescue captura exceções; after executa código independentemente de ter havido exceção ou não.

A lenda diz que, na primeira vez que um programador usou try/rescue, ele perguntou: "Por que ninguém usa isso?" O instrutor respondeu: "Porque ninguém quer cair."

O fato por trás da lenda: try/rescue permite capturar exceções com try, rescue, after e else. A comunidade Elixir prefere usar case com tuplas {:ok, _} e {:error, _} para fluxos esperados.

Gancho: A rede de segurança existe. Mas há uma coisa que simplifica as condições: o cond.


Capítulo 39 — cond (Parte 3): A Escada de Condições que Nunca Para

A lenda diz que o cond é uma escada. Cada degrau é uma condição. Você sobe a escada até encontrar um degrau verdadeiro. Se nenhum for verdadeiro, o CondClauseError aparece.

A verdade é que cond é uma expressão que avalia uma série de condições e executa o corpo da primeira que for verdadeira. Se nenhuma for verdadeira, uma exceção CondClauseError é levantada.

A lenda diz que, na primeira vez que um programador usou cond, ele perguntou: "E se nenhuma condição for verdadeira?" O instrutor respondeu: "Aí você chora."

O fato por trás da lenda: cond avalia uma série de condições e executa o corpo da primeira que for verdadeira. Se nenhuma for verdadeira, uma exceção CondClauseError é levantada.

Gancho: A escada sobe. Mas há uma coisa que percorre listas: as compreensões.


Capítulo 40 — with (Parte 3): A Special Form que Simplifica o Fluxo

A lenda diz que o with é um feitiço. Ele pega várias expressões, e só continua se todas elas casarem. Se uma falhar, o else aparece.

A verdade é que with é uma special form do Elixir (Kernel.SpecialForms.with/1). Ele permite encadear várias expressões com pattern matching. Cada expressão é avaliada em ordem; se uma falhar, o else (se presente) é executado.

A lenda diz que, na primeira vez que um programador usou with, ele perguntou: "Isso substitui case?" O instrutor respondeu: "Não. Substitui case aninhado."

O fato por trás da lenda: with é uma special form (Kernel.SpecialForms.with/1). Ele permite encadear expressões com pattern matching, executando o else se alguma falhar.

Gancho: O with simplifica. Mas há uma coisa que explica: o case.


Epílogo Parcial do Tomo IV

Quarenta capítulos. Uma sintaxe. Mil processos. E um brasileiro que ouviu um sussurro.

Este foi o começo do Tomo IV — A Sintaxe. Ainda faltam 60 capítulos para completar este tomo. Nos próximos, vamos explorar: binários, strings, listas, mapas, tuplas, átomos, números, e muitos outros tópicos.

Até lá.


Agora, sério: Em Elixir, o operador = é o operador de match. O pin operator (^) faz match contra o valor de uma variável existente. O pipe operator (|>) foi inspirado no F#. Module attributes servem para documentação, tipospecs e dados em tempo de compilação. Macros recebem AST como entrada e retornam AST como saída. Guards usam when para verificações complexas. Structs são mapas com __struct__. Protocols permitem polimorfismo. Sigils começam com ~. with é uma special form. case compara um valor com padrões. try/rescue captura exceções. cond avalia condições. Compreensões (for) geram listas. Binários e bitstrings usam <<>>. Strings são binários UTF-8. Listas são listas ligadas. Tuplas são imutáveis. Mapas são pares chave-valor. Keyword lists são listas de tuplas. Átomos são constantes nomeadas. String.to_atom/1 pode causar vazamento de memória. Números são inteiros ou floats. Decimal fornece precisão arbitrária. Enumerable é um protocolo. Stream é preguiçoso. Enum transforma coleções. As capivaras quânticas não são reais — mas deveriam ser. Este artigo é uma fantasia satírica baseada em fatos. Mantenha o aviso para não enganar ninguém.

Top comments (0)