# 5. APIs e Colecoes

### **📋 ÍNDICE**

1. Visão Geral da Biblioteca Padrão
2. Módulos Essenciais
3. Tipos e Estruturas
4. Protocolos
5. Exceções e Erros
6. Módulos de Comportamento (Behaviours)
7. Módulos de Trabalho com Dados
8. Módulos de IO e Sistema
9. Módulos de Concorrência
10. Módulos de Metaprogramação
11. Referência Rápida por Categoria

***

### 🎯 **1. VISÃO GERAL DA BIBLIOTECA PADRÃO**

```yaml
A BIBLIOTECA PADRÃO DO ELIXIR É DIVIDIDA EM:

  🏗️ MÓDULOS FUNDACIONAIS:
    - Kernel: Funções básicas da linguagem (presentes em todo escopo)
    - Kernel.SpecialForms: Construções especiais da linguagem
  
  📦 MÓDULOS DE DADOS:
    - Tipos básicos: Integer, Float, Atom, String, List, Tuple, Map
    - Coleções: Enum, Stream, List, Map, Keyword, MapSet
  
  🔧 MÓDULOS DE UTILIDADES:
    - IO: Entrada e saída
    - File: Manipulação de arquivos
    - Path: Caminhos de arquivos
    - System: Interação com o sistema
  
  ⚡ MÓDULOS DE CONCORRÊNCIA:
    - Task: Tarefas assíncronas
    - Agent: Estado compartilhado
    - GenServer: Servidores genéricos
    - Supervisor: Árvores de supervisão
    - Registry: Registro de processos
  
  🛡️ MÓDULOS DE TRATAMENTO DE ERRO:
    - Exception: Funções para exceções
    - Todas as exceções padrão
```

***

### 🏗️ **2. MÓDULOS ESSENCIAIS**

#### **2.1 Kernel - O Core do Elixir**

```elixir
# O módulo Kernel está disponível em todo escopo (não precisa de import)

# Operadores básicos
1 + 2          # Kernel.+/2
true and false # Kernel.and/2

# Funções de controle
if true, do: :ok, else: :error
unless false, do: :ok

# Funções de tipo
is_integer(1)    # true
is_atom(:ok)     # true
is_binary("ok")  # true

# Comparação
1 == 1.0    # true (valores iguais)
1 === 1.0   # false (tipos diferentes)

# Conversão
to_string(123)  # "123"
to_atom("ok")   # :ok

# Estruturas de controle
case valor do
  :ok -> "Sucesso"
  _ -> "Erro"
end

cond do
  x > 0 -> :positivo
  x < 0 -> :negativo
  true -> :zero
end

# Funções anônimas
fn x -> x + 1 end
&(&1 + 1)
```

#### **2.2 Kernel.SpecialForms - Construções Especiais**

```elixir
# Estas formas não podem ser sobrescritas

# quote - Retorna a representão AST do código
quote do
  1 + 2
end
# {:+, [context: Elixir, import: Kernel], [1, 2]}

# unquote - Injetar código no quote
x = 3
quote do
  1 + unquote(x)  # 1 + 3
end

# alias - Apelido para módulo
alias MeuModulo.Longo, as: M

# require - Carregar macros
require Integer

# import - Importar funções
import Enum, only: [map: 2]

# super - Chamar função da superclasse
defmodule Filho do
  def funcao, do: super()
end

# catch - Capturar throw
try do
  throw(:valor)
catch
  :valor -> :capturado
end
```

#### **2.3 Module - Trabalhando com Módulos**

```elixir
defmodule Exemplo do
  @moduledoc "Documentação do módulo"
  @doc "Documentação da função"
  def funcao, do: :ok
  
  @before_compile __MODULE__
  defmacro __before_compile__(env), do: quote do: def gerado, do: :ok
  def __using__(opts), do: quote do: import unquote(__MODULE__)
end

# Funções úteis do módulo Module
Module.defines_in(Exemplo)     # Lista funções definidas
Module.get_attribute(Exemplo, :moduledoc)  # Pega atributo
Module.put_attribute(Exemplo, :custom, 42)  # Seta atributo
```

***

### 📦 **3. TIPOS E ESTRUTURAS**

#### **3.1 Tipos Básicos**

```elixir
# Atom
Atom.to_string(:ok)        # "ok"
Atom.to_charlist(:ok)      # 'ok'

# Integer
Integer.is_odd(5)          # true
Integer.is_even(4)         # true
Integer.to_string(123)     # "123"
Integer.parse("123")       # {123, ""}

# Float
Float.round(3.14159, 2)    # 3.14
Float.ceil(3.14)           # 4.0
Float.floor(3.14)          # 3.0
Float.to_string(3.14)      # "3.14"

# String
String.length("Hello")      # 5
String.upcase("hello")      # "HELLO"
String.downcase("WORLD")    # "world"
String.trim("  hi  ")       # "hi"
String.split("a,b,c", ",")  # ["a", "b", "c"]
String.join(["a", "b"], "-")# "a-b"
String.contains?("elixir", "xi")  # true
String.replace("hello", "el", "a")  # "halo"

# List
List.first([1, 2, 3])       # 1
List.last([1, 2, 3])        # 3
List.flatten([1, [2, [3]]]) # [1, 2, 3]
List.duplicate(:ok, 3)      # [:ok, :ok, :ok]
List.wrap(nil)              # []
List.wrap(1)                # [1]

# Tuple
Tuple.append({1, 2}, 3)     # {1, 2, 3}
Tuple.delete_at({1, 2, 3}, 1)  # {1, 3}
Tuple.duplicate(:ok, 3)     # {:ok, :ok, :ok}
Tuple.insert_at({1, 3}, 1, 2) # {1, 2, 3}

# Map
Map.get(%{a: 1}, :a)        # 1
Map.put(%{a: 1}, :b, 2)     # %{a: 1, b: 2}
Map.delete(%{a: 1, b: 2}, :a)  # %{b: 2}
Map.merge(%{a: 1}, %{b: 2}) # %{a: 1, b: 2}
Map.keys(%{a: 1, b: 2})     # [:a, :b]
Map.values(%{a: 1, b: 2})   # [1, 2]

# Keyword
Keyword.get([a: 1, b: 2], :a)  # 1
Keyword.put([a: 1], :b, 2)     # [a: 1, b: 2]
Keyword.delete([a: 1, b: 2], :a)  # [b: 2]
Keyword.has_key?([a: 1], :a)   # true
Keyword.keys([a: 1, b: 2])     # [:a, :b]
Keyword.values([a: 1, b: 2])   # [1, 2]

# MapSet
MapSet.new([1, 2, 3])          # MapSet<[1, 2, 3]>
MapSet.put(MapSet.new([1]), 2) # MapSet<[1, 2]>
MapSet.delete(MapSet.new([1, 2]), 1)  # MapSet<[2]>
MapSet.member?(MapSet.new([1]), 1)    # true
MapSet.union(MapSet.new([1]), MapSet.new([2]))  # MapSet<[1, 2]>
MapSet.intersection(MapSet.new([1, 2]), MapSet.new([2, 3]))  # MapSet<[2]>
```

#### **3.2 Estruturas de Tempo**

```elixir
# Date - Data (ano, mês, dia)
date = ~D[2024-01-15]
Date.to_string(date)                    # "2024-01-15"
Date.day_of_week(date)                  # 1 (segunda)
Date.day_of_year(date)                  # 15

# Time - Hora (hora, minuto, segundo, microssegundo)
time = ~T[14:30:45]
Time.to_string(time)                    # "14:30:45"
Time.add(time, 3600)                    # +1 hora

# NaiveDateTime - Data e hora sem fuso
ndt = ~N[2024-01-15 14:30:45]
NaiveDateTime.to_string(ndt)            # "2024-01-15 14:30:45"
NaiveDateTime.add(ndt, 86400)           # +1 dia

# DateTime - Data e hora com fuso
dt = ~U[2024-01-15 14:30:45Z]
DateTime.to_string(dt)                  # "2024-01-15 14:30:45Z"
DateTime.shift_zone(dt, "America/Sao_Paulo", Calendar.ISO)

# Duration - Duração
duration = %Duration{day: 1, hour: 2, minute: 30}
Duration.to_string(duration)            # "P1DT2H30M"
```

***

### 🔧 **4. PROTOCOLOS**

#### **4.1 Principais Protocolos**

```elixir
# Enumerable - Coleções que podem ser enumeradas
defimpl Enumerable, for: MeuTipo do
  def count(list), do: {:ok, length(list)}
  def member?(list, value), do: {:ok, value in list}
  def reduce(list, acc, fun), do: do_reduce(list, acc, fun)
end

# Collectable - Onde podemos coletar valores
defimpl Collectable, for: MeuTipo do
  def into(original) do
    {:ok, original, &do_into(&1, &2)}
  end
end

# Inspect - Representação textual para debugging
defimpl Inspect, for: MeuTipo do
  def inspect(struct, opts) do
    "#MeuTipo<#{struct.valor}>"
  end
end

# String.Chars - Conversão para string
defimpl String.Chars, for: MeuTipo do
  def to_string(struct), do: "#{struct.valor}"
end

# List.Chars - Conversão para charlist
defimpl List.Chars, for: MeuTipo do
  def to_charlist(struct), do: to_charlist(to_string(struct))
end

# JSON.Encoder - Codificação JSON (Jason)
defimpl Jason.Encoder, for: MeuTipo do
  def encode(struct, opts) do
    Jason.Encode.string(struct.valor, opts)
  end
end
```

#### **4.2 Protocolos Built-in**

| Protocolo        | Função Principal              | Uso                     |
| ---------------- | ----------------------------- | ----------------------- |
| **Enumerable**   | `Enum.map/2`, `Enum.reduce/3` | Iteração sobre coleções |
| **Collectable**  | `Enum.into/2`                 | Construção de coleções  |
| **Inspect**      | `inspect/1`, `IO.inspect/1`   | Debugging e logging     |
| **String.Chars** | `to_string/1`                 | Conversão para string   |
| **List.Chars**   | `to_charlist/1`               | Conversão para charlist |
| **JSON.Encoder** | `Jason.encode!/1`             | Codificação JSON        |

***

### 📝 **5. EXCEÇÕES E ERROS**

#### **5.1 Exceções Comuns**

```elixir
# Erros aritméticos
ArithmeticError  # Divisão por zero
ArgumentError    # Argumento inválido
BadArityError    # Aridade errada
BadBooleanError  # Booleano esperado
BadFunctionError # Função esperada
BadMapError      # Mapa esperado

# Erros de casamento
CaseClauseError  # case sem cláusula
CondClauseError  # cond sem cláusula
FunctionClauseError  # função sem cláusula
MatchError       # pattern match falhou
TryClauseError   # try sem cláusula
WithClauseError  # with sem cláusula

# Erros de sintaxe
SyntaxError      # Erro de sintaxe
TokenMissingError  # Token faltando
MismatchedDelimiterError # Delimitador incorreto

# Erros de arquivo
File.Error
File.CopyError
File.RenameError
File.LinkError

# Erros de sistema
SystemLimitError
System.EnvError

# Outros
KeyError         # Chave não encontrada
Protocol.UndefinedError  # Protocolo não implementado
RuntimeError     # Erro genérico
UndefinedFunctionError  # Função não definida
UnicodeConversionError  # Erro Unicode
```

#### **5.2 API de Exceções**

```elixir
# Exception - Funções para trabalhar com exceções
Exception.message(exception)          # Mensagem da exceção
Exception.stacktrace(exception)       # Stack trace
Exception.format(:error, exception, __STACKTRACE__)  # Formatação

# raise/1, raise/2 - Levantar exceção
raise "Erro genérico"
raise ArgumentError, message: "Argumento inválido"

# reraise/2 - Relançar com stacktrace
try do
  erro()
rescue
  e -> reraise e, __STACKTRACE__
end
```

***

### ⚙️ **6. MÓDULOS DE TRABALHO COM DADOS**

#### **6.1 Enum - API de Coleções**

```elixir
# Transformação
Enum.map([1, 2, 3], &(&1 * 2))          # [2, 4, 6]
Enum.flat_map([1, 2], &([&1, &1]))      # [1, 1, 2, 2]

# Filtragem
Enum.filter([1, 2, 3, 4], &(&1 > 2))    # [3, 4]
Enum.reject([1, 2, 3, 4], &(&1 > 2))    # [1, 2]
Enum.take([1, 2, 3, 4], 2)              # [1, 2]
Enum.drop([1, 2, 3, 4], 2)              # [3, 4]

# Agregação
Enum.reduce([1, 2, 3], 0, &+/2)         # 6
Enum.sum([1, 2, 3])                     # 6
Enum.product([2, 3, 4])                 # 24

# Busca
Enum.find([1, 2, 3], &(&1 > 1))         # 2
Enum.any?([1, 2, 3], &(&1 > 2))         # true
Enum.all?([1, 2, 3], &(&1 > 0))         # true

# Ordenação
Enum.sort([3, 1, 2])                    # [1, 2, 3]
Enum.sort_by([%{v: 3}, %{v: 1}], & &1.v) # [%{v: 1}, %{v: 3}]
Enum.uniq([1, 2, 2, 3])                 # [1, 2, 3]

# Transformação com índice
Enum.with_index(["a", "b", "c"])        # [{"a",0},{"b",1},{"c",2}]

# Combinação
Enum.zip([1, 2, 3], [:a, :b, :c])       # [{1,:a},{2,:b},{3,:c}]
Enum.join(["a", "b", "c"], "-")         # "a-b-c"

# Contagem
Enum.count([1, 2, 3])                   # 3
Enum.count([1, 2, 3], &(&1 > 1))        # 2
Enum.empty?([])                         # true

# Conversão
Enum.into([1, 2, 3], %{})               # %{1 => 1, 2 => 2, 3 => 3}
```

#### **6.2 Stream - Processamento Preguiçoso**

```elixir
# Criação de streams
Stream.map([1, 2, 3], &(&1 * 2))        # Stream
Stream.filter([1, 2, 3], &(&1 > 1))     # Stream
Stream.reject([1, 2, 3], &(&1 > 1))     # Stream
Stream.flat_map([1, 2], &([&1, &1]))    # Stream

# Streams infinitos
Stream.iterate(0, &(&1 + 1))            # 0, 1, 2, 3, ...
Stream.cycle([1, 2, 3])                 # 1, 2, 3, 1, 2, 3, ...
Stream.repeatedly(&:random.uniform/0)   # números aleatórios

# Transformação de streams
Stream.chunk_every([1, 2, 3, 4, 5], 2) # [[1,2],[3,4],[5]]
Stream.scan([1, 2, 3], 0, &+/2)        # [0,1,3,6]

# Execução
stream = [1, 2, 3] |> Stream.map(&(&1 * 2))
Enum.to_list(stream)                    # [2, 4, 6]

# Uso com arquivos grandes
File.stream!("dados.csv")
|> Stream.map(&String.trim/1)
|> Stream.filter(&(&1 != ""))
|> Stream.map(&String.split(&1, ","))
|> Enum.take(10)
```

#### **6.3 Regex - Expressões Regulares**

```elixir
# Criação
regex = ~r/hello/
regex = Regex.compile!("^[a-z]+$")
regex = ~r/hello/i  # case insensitive

# Matching
Regex.match?(~r/hello/, "hello world")      # true
Regex.run(~r/\d+/, "abc123def")             # ["123"]
Regex.scan(~r/\w+/, "hello world")          # [["hello"], ["world"]]

# Substituição
Regex.replace(~r/\s+/, "a b c", "-")        # "a-b-c"
Regex.replace(~r/\d+/, "abc123def", "X")    # "abcXdef"

# Nomes de grupos
Regex.named_captures(~r/(?<name>\w+)/, "hello")  # %{"name" => "hello"}

# Opções
Regex.compile!("pattern", [:caseless, :unicode])
```

***

### 🖥️ **7. MÓDULOS DE IO E SISTEMA**

#### **7.1 IO - Entrada e Saída**

```elixir
# Saída
IO.puts("Hello")                # "Hello\n"
IO.write("Hello")               # "Hello"
IO.inspect(%{a: 1})            # %{a: 1}\n
IO.inspect(%{a: 1}, label: "Dados")

# Formatação
IO.write("Número: #{123}")      # "Número: 123"
IO.puts(:stderr, "Erro")        # escreve no stderr

# Entrada
IO.gets("Digite algo: ")        # lê linha
IO.read(:stdio, :line)          # lê linha

# IO.ANSI - Cores e formatação
IO.puts(IO.ANSI.red() <> "Texto vermelho" <> IO.ANSI.reset())
IO.puts(IO.ANSI.format([:red, "Texto", :reset]))
IO.puts(IO.ANSI.format([:bright, :green_background, "Destaque"]))

# IO.Stream - Streaming de dados
IO.stream(:stdio, :line)
|> Stream.map(&String.trim/1)
|> Enum.each(&IO.puts/1)
```

#### **7.2 File - Manipulação de Arquivos**

```elixir
# Leitura
File.read("arquivo.txt")                    # {:ok, conteudo}
File.read!("arquivo.txt")                   # conteudo ou erro
File.stream!("arquivo.txt")                 # Stream de linhas

# Escrita
File.write("arquivo.txt", "conteudo")       # :ok
File.write!("arquivo.txt", "conteudo")      # :ok
File.write("arquivo.txt", "mais", [:append])# append

# Diretórios
File.ls()                                   # lista arquivos
File.ls("/tmp")                             # lista diretório
File.mkdir("novo_dir")                      # cria diretório
File.mkdir_p("path/para/dir")               # cria diretórios aninhados
File.rm_rf("dir")                           # remove recursivamente
File.cd("dir")                              # muda diretório
File.cwd()                                  # diretório atual

# Informações
File.exists?("arquivo.txt")                 # true/false
File.regular?("arquivo.txt")                # é arquivo normal
File.dir?("dir")                            # é diretório
File.stat("arquivo.txt")                    # %File.Stat{}
File.size("arquivo.txt")                    # tamanho em bytes

# Copiar, mover, renomear
File.cp("origem.txt", "destino.txt")
File.mv("origem.txt", "destino.txt")
File.rename("velho.txt", "novo.txt")
File.ln("origem.txt", "link.txt")           # hard link
File.ln_s("origem.txt", "link_sym.txt")     # sym link

# Path - manipulação de caminhos
Path.join("dir", "file.txt")                # "dir/file.txt"
Path.expand("~/file.txt")                   # "/home/user/file.txt"
Path.absname("file.txt")                    # caminho absoluto
Path.basename("/path/file.txt")             # "file.txt"
Path.dirname("/path/file.txt")              # "/path"
Path.extname("file.txt")                    # ".txt"
Path.rootname("file.txt")                   # "file"
Path.split("/a/b/c")                        # ["/", "a", "b", "c"]
Path.relative_to("/a/b/c", "/a")            # "b/c"
Path.wildcard("*.ex")                       # ["a.ex", "b.ex"]

# Path para construção de caminhos
Path.expand("~/projeto/config.exs")
|> Path.dirname()
|> Path.join("lib")
|> Path.expand()
```

#### **7.3 System - Interação com o Sistema**

```elixir
# Informações do sistema
System.version()                        # versão do Erlang/OTP
System.build_info()                     # informações de build
System.cpu_topology()                   # topologia da CPU
System.os_version()                     # versão do SO

# Variáveis de ambiente
System.get_env("PATH")                  # valor da variável
System.get_env("HOME", "/default")      # com valor padrão
System.put_env("MY_VAR", "value")       # set
System.delete_env("MY_VAR")             # remove
System.fetch_env("PATH")                # {:ok, value} ou :error

# Argumentos da linha de comando
System.argv()                           # ["arg1", "arg2"]

# Comandos do shell
System.cmd("ls", ["-la"])               # {output, status}
System.shell("ls -la")                  # {output, status}

# Tempo
System.time(timestamp)                  # tempo de sistema
System.monotonic_time()                 # tempo monotônico
System.unique_integer([:monotonic])     # inteiro único

# Halt
System.halt(0)                          # termina processo (código 0)
System.stop(0)                          # para VM (código 0)
```

***

### ⚡ **8. MÓDULOS DE CONCORRÊNCIA**

#### **8.1 Process - Funções de Processos**

```elixir
# Criação
pid = spawn(fn -> :ok end)             # spawn de função
pid = spawn_link(fn -> :ok end)        # com link
Process.start(Modulo, :fun, [arg])     # start com módulo

# Envio de mensagens
send(pid, {:msg, "conteudo"})

# Recebimento
receive do
  {:msg, msg} -> IO.puts(msg)
after
  5000 -> IO.puts(:timeout)
end

# Informações
Process.alive?(pid)                    # true/false
Process.info(pid)                      # informações detalhadas
Process.list()                         # lista todos os processos
Process.registered()                   # processos registrados

# Registro
Process.register(pid, :meu_processo)   # registra nome
Process.whereis(:meu_processo)         # obtém PID
Process.unregister(:meu_processo)      # desregistra

# Flags
Process.flag(:trap_exit, true)         # captura exits
Process.flag(:error_handler, handler)  # handler de erro
Process.flag(:priority, :high)         # prioridade

# Grupos
Process.group_leader()                 # líder do grupo
Process.group_leader(pid, leader)      # set líder
```

#### **8.2 Task - Tarefas Assíncronas**

```elixir
# Criação e execução
task = Task.async(fn -> 1 + 2 end)     # async
result = Task.await(task)               # 3

# Com timeout
Task.await(task, 5000)                  # timeout 5s

# Startup e espera
Task.start(fn -> :ok end)               # start
Task.start_link(fn -> :ok end)          # start e link

# Múltiplas tarefas
tasks = [
  Task.async(fn -> 1 + 1 end),
  Task.async(fn -> 2 + 2 end),
  Task.async(fn -> 3 + 3 end)
]
Task.await_many(tasks)                  # [2, 4, 6]

# Supervisão
children = [
  {Task, fn -> :timer.sleep(1000); IO.puts("Pronto") end}
]
Task.Supervisor.start_link(children)

# Stream de tarefas
Task.async_stream([1,2,3], fn x -> x * 2 end)
|> Enum.to_list()                       # [2,4,6]
```

#### **8.3 Agent - Estado Compartilhado**

```elixir
# Criação
{:ok, agent} = Agent.start_link(fn -> [] end)

# Operações
Agent.update(agent, &([:novo | &1]))    # atualiza estado
Agent.get(agent, fn list -> length(list) end)  # obtém

# Completas
value = Agent.get_and_update(agent, fn list ->
  {length(list), [0 | list]}
end)

# Cast (fire and forget)
Agent.cast(agent, fn _ -> 0 end)

# Start com nome
Agent.start_link(fn -> [] end, name: :meu_agent)
Agent.get(:meu_agent, & &1)

# Stop
Agent.stop(agent)
```

#### **8.4 GenServer - Servidor Genérico**

```elixir
defmodule MeuServidor do
  use GenServer
  
  # API do cliente
  def start_link(estado_inicial) do
    GenServer.start_link(__MODULE__, estado_inicial, name: __MODULE__)
  end
  
  def obter_estado do
    GenServer.call(__MODULE__, :obter)
  end
  
  def atualizar(valor) do
    GenServer.cast(__MODULE__, {:atualizar, valor})
  end
  
  # Callbacks
  @impl GenServer
  def init(estado) do
    {:ok, estado}
  end
  
  @impl GenServer
  def handle_call(:obter, _from, estado) do
    {:reply, estado, estado}
  end
  
  @impl GenServer
  def handle_cast({:atualizar, valor}, estado) do
    {:noreply, [valor | estado]}
  end
  
  @impl GenServer
  def terminate(_reason, estado) do
    IO.puts("Servidor terminando com: #{inspect(estado)}")
    :ok
  end
end
```

#### **8.5 Supervisor - Supervisão**

```elixir
defmodule MeuSupervisor do
  use Supervisor
  
  def start_link(opts) do
    Supervisor.start_link(__MODULE__, opts, name: __MODULE__)
  end
  
  @impl Supervisor
  def init(_opts) do
    children = [
      # Worker
      {MeuServidor, []},
      
      # Supervisor aninhado
      {DynamicSupervisor, name: MeuDynamicSupervisor},
      
      # Task
      {Task, fn -> :timer.sleep(1000) end}
    ]
    
    Supervisor.init(children, strategy: :one_for_one)
  end
end

# DynamicSupervisor
defmodule MeuDynamicSupervisor do
  use DynamicSupervisor
  
  def start_link(opts) do
    DynamicSupervisor.start_link(__MODULE__, opts, name: __MODULE__)
  end
  
  def start_child(mod, args) do
    spec = {mod, args}
    DynamicSupervisor.start_child(__MODULE__, spec)
  end
end
```

#### **8.6 Registry - Registro de Processos**

```elixir
# Registry
{:ok, registry} = Registry.start_link(keys: :unique, name: Registry.Processes)

# Registrar
{:ok, _} = Registry.register(registry, "chave", "valor")

# Buscar
Registry.lookup(registry, "chave")      # [{pid, valor}]
Registry.match(registry, "chave", true) # [{pid, valor}]

# Registry local
Registry.start_link(keys: :duplicate, name: Registry.Events)
```

***

### 🔮 **9. MÓDULOS DE METAPROGRAMAÇÃO**

#### **9.1 Code - Compilação e Carregamento**

```elixir
# Compilar string
Code.compile_string("defmodule M, do: def f, do: 1")

# Carregar arquivo
Code.require_file("meu_modulo.ex")
Code.load_file("meu_script.exs")

# Avaliar código
Code.eval_string("1 + 2")               # {3, binding}
Code.eval_string("a + b", [a: 1, b: 2]) # {3, binding}

# Strings disponíveis
Code.string_to_quoted("1 + 2")          # {:+, [], [1, 2]}
Code.quoted_to_string({:+, [], [1, 2]}) # "1 + 2"

# Disponibilidade
Code.ensure_loaded(Enum)               # {:module, Enum}
Code.ensure_compiled(Enum)             # {:module, Enum}
```

#### **9.2 Macro - Ferramentas de Macro**

```elixir
defmodule MeuMacro do
  defmacro quando(condition, do: block) do
    quote do
      if unquote(condition) do
        unquote(block)
      end
    end
  end
  
  defmacro debug(valor) do
    quote do
      IO.puts("#{unquote(Macro.to_string(valor))} = #{unquote(valor)}")
      unquote(valor)
    end
  end
end

# Macro.Env - Ambiente de compilação
defmacro exemplo do
  IO.inspect(__CALLER__.module)        # módulo atual
  IO.inspect(__CALLER__.function)      # função atual
  IO.inspect(__CALLER__.file)          # arquivo atual
  IO.inspect(__CALLER__.line)          # linha atual
  IO.inspect(__CALLER__.aliases)       # aliases ativos
  IO.inspect(__CALLER__.requires)      # requires ativos
  IO.inspect(__CALLER__.imports)       # imports ativos
end
```

***

### 📊 **10. REFERÊNCIA RÁPIDA POR CATEGORIA**&#x20;

#### **10.2 Convenções de Nomenclatura**

```yaml
CONVENÇÕES DE NOMENCLATURA:

  FUNÇÕES QUE RETORNAM TUPLAS COM STATUS:
    - {:ok, resultado}: sucesso
    - {:error, razão}: falha
  
  EXEMPLO:
    File.read("arquivo.txt")  # {:ok, conteúdo} ou {:error, reason}
  
  FUNÇÕES COM VERSÃO BANG (!):
    - Sem !: retorna tupla {:ok, resultado} ou {:error, reason}
    - Com !: retorna resultado ou levanta exceção
  
  EXEMPLO:
    File.read("arquivo.txt")   # {:ok, "conteudo"}
    File.read!("arquivo.txt")  # "conteudo" ou exceção
  
  PREDICADOS (FUNÇÕES QUE RETORNAM BOOLEANO):
    - Terminam com ?: retornam true ou false
  
  EXEMPLO:
    String.contains?("hello", "el")  # true
    Enum.empty?([])                   # true
  
  OPERADORES:
    - Podem ser sobrecarregados (Kernel)
    - Principais: +, -, *, /, ==, ===, !=, !==, <, >, <=, >=, &&, ||, !
```

***

### 🏗️ **11. MÓDULOS ADICIONAIS DA BIBLIOTECA PADRÃO**

#### **11.1 Base - Codificação Base64 e Base32**

```elixir
# Base64
Base.encode64("Hello World")                    # "SGVsbG8gV29ybGQ="
Base.decode64("SGVsbG8gV29ybGQ=")              # {:ok, "Hello World"}

# Com padding opcional
Base.encode64("Hello", padding: false)          # "SGVsbG8"
Base.decode64("SGVsbG8", padding: false)       # {:ok, "Hello"}

# URL-safe Base64
Base.url_encode64("Hello World")                # "SGVsbG8gV29ybGQ="
Base.url_decode64("SGVsbG8gV29ybGQ=")          # {:ok, "Hello World"}

# Base64 personalizado
Base.encode64("dado", alphabet: :urlsafe)      # URL-safe
Base.encode64("dado", padding: false)          # sem padding

# Base32
Base.encode32("Hello")                          # "JBSWY3DP"
Base.decode32("JBSWY3DP")                      # {:ok, "Hello"}

# Base32 hex
Base.encode32("Hello", case: :lower)           # letras minúsculas
Base.decode32("jbsWy3dp", case: :mixed)        # case insensitive
```

#### **11.2 URI - Manipulação de URLs**

```elixir
# Parsing
uri = URI.parse("https://user:pass@example.com:8080/path?query=1#fragment")
# %URI{
#   scheme: "https",
#   userinfo: "user:pass",
#   host: "example.com",
#   port: 8080,
#   path: "/path",
#   query: "query=1",
#   fragment: "fragment"
# }

# Construção
URI.to_string(%URI{scheme: "https", host: "example.com"})  # "https://example.com"

# URI.encode/1 - Codificar caracteres especiais
URI.encode("Hello World")                      # "Hello%20World"
URI.encode("a b&c=d", &URI.char_unreserved?/1) # "a%20b%26c%3Dd"

# URI.decode/1 - Decodificar
URI.decode("Hello%20World")                    # "Hello World"

# Query string
URI.decode_query("name=João&age=30")           # %{"name" => "João", "age" => "30"}
URI.encode_query(%{name: "João", age: 30})     # "name=Jo%C3%A3o&age=30"

# Merge
URI.merge("/path", "https://site.com")         # relative to absolute
```

#### **11.3 Version - Versionamento Semântico**

```elixir
# Parsing de versão
{:ok, version} = Version.parse("1.2.3")
# %Version{major: 1, minor: 2, patch: 3}

# Compare
Version.compare("1.2.3", "1.2.4")               # :lt
Version.compare("2.0.0", "1.9.9")               # :gt

# Match com requirement
req = ">= 1.0.0 and < 2.0.0"
Version.match?("1.5.0", req)                   # true
Version.match?("2.0.0", req)                   # false

# Requerimento parse
{:ok, requirement} = Version.parse_requirement("~> 1.2")

# Conveniência
Version.parse!("1.2.3")                        # levanta exceção
```

#### **11.4 OptionParser - Parsing de CLI**

```elixir
defmodule MeuCli do
  def main(args) do
    # Especificação
    options = [
      verbose: :boolean,
      port: :integer,
      name: :string,
      help: :boolean
    ]
    
    aliases = [
      v: :verbose,
      p: :port,
      n: :name,
      h: :help
    ]
    
    # Parse
    {parsed, argv, invalid} = OptionParser.parse(
      args,
      switches: options,
      aliases: aliases
    )
    
    # Processar
    cond do
      parsed[:help] -> IO.puts("Uso: meu_comando [opções]")
      invalid != [] -> IO.puts("Opções inválidas: #{inspect(invalid)}")
      true ->
        IO.puts("Verbose: #{parsed[:verbose]}")
        IO.puts("Porta: #{parsed[:port]}")
        IO.puts("Nome: #{parsed[:name]}")
        IO.puts("Argumentos restantes: #{inspect(argv)}")
    end
  end
end

# Exemplo de uso
# $ elixir meu_script.exs --verbose --port 8080 --name "João" extra
```

#### **11.5 Config - Configuração de Aplicações**

```elixir
# Escrever configuração (em config/config.exs)
import Config
config :minha_app, :chave, "valor"
config :minha_app, :http, port: 8080, host: "localhost"

# Ler configuração (na aplicação)
Application.get_env(:minha_app, :chave)        # "valor"
Application.get_env(:minha_app, :http)         # [port: 8080, host: "localhost"]

# Configurações por ambiente
config :minha_app, :debug, true

if config_env() == :prod do
  config :minha_app, :debug, false
  config :minha_app, :http, port: 80
end

# Config.Reader - ler arquivos de configuração
{:ok, config} = Config.Reader.read!("config/config.exs")

# Config.Provider - provedor de configuração
defmodule MeuProvider do
  @behaviour Config.Provider
  def init(opts), do: opts
  def load(config, _opts) do
    Config.Reader.merge(config, %{minha_app: [chave: "valor"]})
  end
end
```

***

### ⚙️ **12. MÓDULOS DE DEPURAÇÃO E TESTE**

#### **12.1 IO.inspect/2 - Debugging**

```elixir
# Inspecionar valor durante pipeline
[1, 2, 3]
|> IO.inspect(label: "Original")
|> Enum.map(&(&1 * 2))
|> IO.inspect(label: "Multiplicado")

# Opções
IO.inspect(valor, 
  label: "Debug",           # rótulo
  limit: 50,                # limita estruturas grandes
  printable_limit: 1000,    # limite de strings
  width: 80,                # largura da saída
  pretty: true,             # pretty print
  structs: false            # não printa structs
)

# Inspect via to_string
inspect([1, 2, 3])          # "[1, 2, 3]"
inspect(%{a: 1}, pretty: true)
```

#### **12.2 IEx - Interactive Elixir**

```elixir
# Dentro do IEx
h Enum.map                # ajuda de uma função
i 1 + 2                   # informações do valor
r MeuModulo               # recompilar módulo
c "arquivo.ex"            # compilar arquivo
l MeuModulo               # carregar módulo

# .iex.exs - Configuração personalizada
IO.puts("Carregando IEx...")
IEx.configure(
  colors: [enabled: true],
  default_prompt: ">>> "
)

# IEx.Helpers - Funções auxiliares
import IEx.Helpers
h()                       # lista de helpers
help("Enum")              # ajuda sobre módulo
pid()                     # PID do processo IEx
```

#### **12.3 dbg/2 - Debugging Moderno**

```elixir
# dbg - Novo helper (Elixir 1.15+)
value = 42
dbg(value)                 # mostra valor e retorna

# Em pipelines
[1, 2, 3]
|> dbg()
|> Enum.map(&(&1 * 2))
|> dbg()

# Com múltiplos argumentos
dbg(1 + 2, 3 * 4)          # mostra ambos

# Configuração
IEx.configure(dbg_callback: &MyDebugger.callback/2)
```

#### **12.4 ExUnit - Framework de Testes**

```elixir
defmodule MeuTeste do
  use ExUnit.Case
  doctest MeuModulo
  
  setup do
    {:ok, %{user: "teste"}}
  end
  
  test "soma deve funcionar" do
    assert 1 + 1 == 2
    refute 1 + 1 == 3
  end
  
  test "captura erro", %{user: user} do
    assert_raise ArgumentError, fn -> 
      String.to_integer("abc")
    end
  end
  
  test "assert_errors/2" do
    assert_raise(ArithmeticError, fn -> 1 / 0 end)
  end
  
  test "captura e verifica mensagem" do
    assert_raise(ArgumentError, "argument error", fn -> 
      String.to_atom(123)
    end)
  end
  
  describe "quando usuário é válido" do
    test "login funciona", context do
      assert context.user == "teste"
    end
  end
end

# ExUnit.Callbacks
defmodule CallbacksTest do
  use ExUnit.Case
  
  setup_all do
    IO.puts("Iniciando suite de testes")
    :ok
  end
  
  setup do
    IO.puts("Antes de cada teste")
    {:ok, temp_dir: "/tmp/test"}
  end
  
  on_exit(fn ->
    IO.puts("Depois de cada teste")
  end)
end
```

***

### 📁 **13. MÓDULOS DE Serialização**

#### **13.1 JSON (Jason)**

```elixir
# Jason não é built-in, mas padrão na comunidade
# Adicione {:jason, "~> 1.4"} no mix.exs

# Codificação
Jason.encode!(%{name: "João", age: 30})      # "{\"age\":30,\"name\":\"João\"}"
Jason.encode(%{name: "João"})                # {:ok, "{\"name\":\"João\"}"}

# Decodificação
Jason.decode!("{\"age\":30}")                # %{"age" => 30}
Jason.decode("{\"age\":30}")                 # {:ok, %{"age" => 30}}

# Options
Jason.encode!(%{long_string: "a" * 1000}, 
  pretty: true,                              # identação
  indent: "\t",                              # caractere de indentação
  maps: :arrays                              # ordena keys
)

# Implementar protocolo
defimpl Jason.Encoder, for: MyStruct do
  def encode(struct, opts) do
    Jason.Encode.map(%{field: struct.field}, opts)
  end
end
```

#### **13.2 Protocol Buffers (Protobuf)**

```elixir
# Protobuf (com biblioteca protobuf-elixir)

# Definir .proto
syntax = "proto3";
message Person {
  string name = 1;
  int32 age = 2;
}

# Gerar módulo
defmodule Person do
  use Protobuf, syntax: :proto3
  defstruct [:name, :age]
  field :name, 1, type: :string
  field :age, 2, type: :int32
end

# Codificar
person = %Person{name: "Alice", age: 25}
encoded = Person.encode(person)
decoded = Person.decode(encoded)
```

***

### 🌐 **14. MÓDULOS DE REDE**

#### **14.1 HTTP/1 Client (Built-in)**

```elixir
# :httpc - cliente HTTP do Erlang

# Request básico
{:ok, {{version, status, reason}, headers, body}} = 
  :httpc.request(:get, {'http://example.com', []}, [], [])

# Com opções
opts = [
  timeout: 5000,
  connect_timeout: 2000
]

{:ok, {{_, 200, _}, _, body}} = 
  :httpc.request(:get, {'https://api.example.com', []}, opts, [])

# POST request
headers = [{'Content-Type', 'application/json'}]
body = ~s({"name": "João"})
request = {:post, {'https://api.example.com/users', headers}, "application/json", body}

{:ok, {{_, status, _}, _, _}} = :httpc.request(request)
```

#### **14.2 Stream de Rede**

```elixir
# Socket TCP básico
{:ok, socket} = :gen_tcp.connect('localhost', 8080, [:binary, packet: :line])
:gen_tcp.send(socket, "GET / HTTP/1.0\r\n\r\n")

receive do
  {:tcp, socket, data} -> IO.puts(data)
  {:tcp_closed, socket} -> IO.puts("Conexão fechada")
end

# Servidor TCP simples
defmodule TcpServer do
  def start(port) do
    {:ok, listen_socket} = :gen_tcp.listen(port, [:binary, packet: :line, reuseaddr: true])
    accept_loop(listen_socket)
  end
  
  defp accept_loop(listen_socket) do
    {:ok, socket} = :gen_tcp.accept(listen_socket)
    Task.start(fn -> handle_client(socket) end)
    accept_loop(listen_socket)
  end
  
  defp handle_client(socket) do
    :gen_tcp.send(socket, "Hello World!\n")
    :gen_tcp.close(socket)
  end
end
```

***

### 🔧 **15. FUNÇÕES ÚTEIS ADICIONAIS**

#### **15.1 Miscelânea**

```elixir
# Erlang :rand - números aleatórios
:rand.uniform()              # float 0.0 - 1.0
:rand.uniform(10)            # inteiro 1 - 10
:rand.normal()               # distribuição normal

# Erlang :crypto - funções criptográficas
:crypto.hash(:sha256, "dado")
:crypto.strong_rand_bytes(32)

# Calendário
Calendar.ISO.day_of_week(2024, 1, 15)    # 1 (segunda)
Calendar.ISO.leap_year?(2024)            # true

# Range
range = 1..10
Enum.to_list(range)                      # [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]]

# Bitwise (use Bitwise)
import Bitwise
1 &&& 3                                 # 1 (AND)
1 ||| 2                                 # 3 (OR)
1 ^^^ 3                                 # 2 (XOR)
1 <<< 2                                 # 4 (shift left)

# Float
Float.ceil(3.14, 1)                     # 3.2
Float.floor(3.14, 1)                    # 3.1
Float.round(3.14, 1)                    # 3.1
Float.to_string(3.14, decimals: 4)      # "3.1400"

# Integer
Integer.digits(123)                     # [1, 2, 3]
Integer.undigits([1, 2, 3])             # 123
Integer.to_charlist(123)                # '123'
Integer.parse("123", 10)                # {123, ""}

# StringIO
{:ok, io} = StringIO.open("texto")
StringIO.contents(io)                    # {"texto", ""}
StringIO.close(io)
```

***

### 📚 **16. BIBLIOTECAS COMUNS DA COMUNIDADE**

| Biblioteca       | Descrição                 | Uso Típico                   |
| ---------------- | ------------------------- | ---------------------------- |
| **Phoenix**      | Framework web             | Aplicações web em tempo real |
| **Ecto**         | ORM e consultas           | Acesso a banco de dados      |
| **Plug**         | Especificação de conexões | Middleware web               |
| **Jason**        | JSON encoding/decoding    | Serialização JSON            |
| **Tesla**        | Cliente HTTP              | Cliente HTTP flexível        |
| **Finch**        | Cliente HTTP rápido       | Requisições HTTP             |
| **Req**          | Cliente HTTP moderno      | Requisições HTTP             |
| **NimbleParsec** | Parser combinators        | Parsers de texto             |
| **Flow**         | Processamento paralelo    | Dados em fluxo               |
| **Broadway**     | Pipelines de dados        | Processamento de dados       |
| **GenStage**     | Pipeline de eventos       | Processamento passo a passo  |
| **Obán**         | Gerenciamento de jobs     | Tarefas agendadas            |

***

### 🔗 **17. REFERÊNCIAS E LINKS ÚTEIS**

#### **Documentação Oficial**

* [HexDocs - Documentação oficial](https://hexdocs.pm/elixir/)
* [Elixir School - Tutoriais](https://elixirschool.com/pt)
* [Learn Elixir - Guia oficial](https://elixir-lang.org/learning.html)

#### **Principais Bibliotecas**

* [Phoenix Framework](https://www.phoenixframework.org/)
* [Ecto](https://hexdocs.pm/ecto/)
* [Plug](https://hexdocs.pm/plug/)

#### **Cheatsheets**

* [Elixir Cheatsheet](https://elixir-lang.org/cheatsheet.html)
* [Enum Cheatsheet](https://hexdocs.pm/elixir/enum-cheat.html)

***

### ⚠️ **18. CONSIDERAÇÕES FINAIS**

#### **Estilo e Padrões**

```elixir
# Use pipe operator
"hello"
|> String.upcase()
|> String.trim()

# Pattern matching sobre if/else
case result do
  {:ok, value} -> process(value)
  {:error, reason} -> handle_error(reason)
end

# Capture operator para funções curtas
Enum.map(list, &(&1 * 2))

# Documentação clara
@moduledoc """
Documentação do módulo.
"""
@doc """
Documentação da função.
"""
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://0xmorte.gitbook.io/bibliadopentestbr/conceitos/programacao-e-linguagens/elixir/5.-apis-e-colecoes.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
