- A versão Elixir 1.19 permite detectar mais bugs com mais rapidez por meio do fortalecimento do sistema de tipos e de melhorias no desempenho de compilação
- A inferência de tipos foi expandida para funções anônimas e protocolos, permitindo uma validação automática mais ampla mesmo sem anotações de tipo do usuário
- Em projetos grandes, oferece velocidade de compilação até 4 vezes maior, incluindo compilação paralela e otimização do carregamento de código
- Também foram reforçados o ecossistema e a transparência da cadeia de suprimentos, com suporte ao Erlang/OTP 28 e adoção da certificação OpenChain
- Além disso, inclui vários recursos como melhorias no parsing de opções, mais capacidades de depuração no ExUnit e melhor acessibilidade à documentação baseada em shell
Principais melhorias do Elixir 1.19
Melhorias no sistema de tipos
Inferência de tipos em todos os componentes
- Type inference (inferência de tipos) é um recurso que determina automaticamente o tipo de expressões em tempo de compilação
- Antes, a ideia era oferecer suporte à inferência de tipos principalmente em padrões, guards e valores de retorno, mas nesta release foi introduzida a inferência de tipos para todos os componentes (exceto guards)
- Como a inferência considera também chamadas a funções dentro do módulo e funções da biblioteca padrão do Elixir, funções que antes eram inferidas como
dynamic() -> boolean() agora podem ser inferidas de forma mais precisa, como integer() -> boolean()
- A inferência de tipos envolve vários trade-offs, como velocidade de compilação, expressividade, compilação incremental e clareza de erros; no futuro, também deverá incluir inferência de tipos em guards e informações de tipos de dependências
- Quando uma assinatura de tipo é explicitamente declarada em uma função, isso passa a funcionar como verificação de tipo explícita, e não inferência, permitindo apenas os tipos compatíveis com a anotação do usuário
Verificação de tipos em despacho e implementação de protocolos
- O Elixir agora aplica verificação de tipos em chamadas e implementações de protocolos
- Por exemplo, ao passar para interpolação de string um tipo que não implementa o protocolo
String.Chars, o compilador emite uma mensagem de aviso
- Em comprehensions
for, também é emitido um aviso ao passar como gerador um tipo que não satisfaz o protocolo Enumerable
- Essas verificações de tipo ajudam a evitar mais bugs em tempo de compilação
Inferência e verificação de tipos para funções anônimas
- O Elixir 1.19 oferece suporte a inferência de tipos e verificação de tipos para funções anônimas
- Por exemplo, se uma função anônima espera um tipo
%{} e recebe um tipo incorreto como "hello", isso pode ser detectado imediatamente como aviso em tempo de compilação
- A inferência de tipos também se aplica a function captures (
&String.to_integer/1 etc.), ampliando o alcance da validação automática de tipos
Referências e parceiros
- Esse sistema de tipos foi desenvolvido em parceria entre a CNRS e a Remote
- Fresha, *Starfish* *, Dashbit e outras apoiaram o projeto
Compilação mais rápida em projetos grandes
Melhoria no gargalo de carregamento de código
- Antes, os módulos eram carregados imediatamente após a definição, mas nesta release isso mudou para uma estratégia de lazy loading (carregamento sob demanda)
- Com isso, a carga sobre o code server foi reduzida e o desempenho da compilação paralela melhorou, aumentando em mais de 2 vezes a velocidade de compilação de projetos grandes
- Dois pontos principais de atenção
- Ao criar processos separados durante a compilação para acessar módulos do mesmo projeto, o carregamento pode não ocorrer; para contornar isso, use
Kernel.ParallelCompiler.pmap/2 ou Code.ensure_compiled!/1
- Ao chamar módulos do mesmo projeto dentro do callback
@on_load, pode haver erro; se necessário, use a opção @compile {:autoload, true}
- Em ambos os casos, antes podiam ocorrer erros de compilação não determinísticos, mas com essa melhoria passa a haver um ambiente de compilação determinístico (reproduzível)
Compilação paralela de dependências
- Com a variável de ambiente
MIX_OS_DEPS_COMPILE_PARTITION_COUNT, passou a haver suporte à compilação paralela de dependências
- Como múltiplos processos do sistema operacional são usados ao mesmo tempo para compilar dependências em paralelo, o desempenho de compilação pode melhorar em até 4 vezes, dependendo do tamanho do projeto e do número de núcleos da CPU
- Experimentalmente, definir um valor em torno de metade do total de núcleos tende a ser eficaz para o uso de recursos
- Como a paralelização pode aumentar o uso de memória, é preciso cautela ao aplicá-la em CI ou servidores de build
Suporte ao Erlang/OTP 28
- O Elixir 1.19 oferece suporte oficial ao Erlang/OTP 28.1+
- Devido a mudanças na representação de expressões regulares no Erlang/OTP 28, não é mais possível usar expressões regulares como valor padrão de structs
- Na inicialização de structs, ainda é possível usar expressões regulares
Adoção da certificação OpenChain
- Esta release é a primeira versão a iniciar a conformidade com o padrão OpenChain
- Cada release inclui um SBoM (Source Bill of Materials) nos formatos CycloneDX 1.6/SPDX 2.3
- Isso aumenta a transparência da cadeia de suprimentos em relação aos componentes e licenças da release, contribuindo para um controle mais rigoroso
- Esse trabalho foi realizado por Jonatan Männchen, com apoio da Erlang Ecosystem Foundation
Outras melhorias
- Foram adicionadas diversas melhorias em ferramentas e bibliotecas, incluindo parsing de opções, depuração e desempenho do ExUnit, e acessibilidade à documentação baseada em shell
- Para notas de release mais detalhadas, consulte o CHANGELOG
1 comentários
Opiniões do Hacker News
Destaca que a forma como o Elixir está introduzindo gradualmente a verificação automática de tipos é um excelente exemplo de evolução de linguagem do qual outras linguagens de programação também poderiam aprender; há muitos casos em que mudanças grandes dividiram o ecossistema em dois, e é reconfortante que José tenha deixado claro desde 2018 que a linguagem em si já estava concluída; como a linguagem e o core não vão mais quebrar, isso transmite muita estabilidade; recomenda a palestra relacionada; ficou impressionado com a condução consistente e excelente
O Elixir continua evoluindo de forma estável, lançando ótimos recursos e melhorias de forma consistente; a estrutura da linguagem é excelente e seus criadores continuam apontando na direção certa, o que é realmente impressionante; a única pena é não ter oportunidades de usar Elixir no dia a dia
Compartilha dados experimentais sobre a velocidade de compilação de dependências do Phoenix; em um app pequeno contendo apenas as dependências padrão do Phoenix, em um Mac M1 Max, os seguintes tempos de compilação foram medidos conforme o valor da variável de ambiente
MIX_OS_DEPS_COMPILE_PARTITION_COUNTO cache foi apagado entre cada teste com o comando
rm -rf _build_buildNos últimos meses passou a gostar muito de Gleam; também ficou feliz com a introdução do sistema de tipos no Elixir, mas antes isso era um dos principais fatores que dificultavam sua adoção do Elixir; gostaria de dar outra chance ao Elixir algum dia, mas teme que acabe sendo algo como o TypeScript no JavaScript, tipado só na aparência, enquanto muitas libs e pacotes continuam basicamente dinâmicos/any; pergunta se essa preocupação faz sentido ou não; o BEAM é realmente fantástico
Elixir parece ser um dos ambientes mais promissores para desenvolvimento web; sempre que encontra organizações ou equipes que usam Elixir no trabalho real, tem a impressão de que o nível delas é acima da média; acha que, em ambientes onde desenvolvimento contínuo é necessário, o Elixir continua fornecendo direção e padrões
Apresenta que a release do Elixir passou a oferecer suporte a formatos de Source SBoM como CycloneDX 1.6+ e SPDX 2.3+; é muito valioso que a gestão de SBOM aconteça no nível da linguagem; infelizmente, a empresa atual não usa Elixir
Se alguém quiser contribuir para um projeto open source em Elixir usado de fato, um dos principais componentes do antigo Mozilla Hubs continua sendo desenvolvido em Elixir como projeto independente; veja Hubs Foundation/reticulum
Com base na biblioteca padrão do Elixir, é possível fazer inferência de tipos em tempo de compilação para situações específicas da aplicação, como converter tipos dinâmicos em booleanos ou inteiros em booleanos
Não tem experiência prática desenvolvendo em Elixir, mas é fã; antes gostava da praticidade e da beleza do Ruby, mas mudou de linguagem ao se interessar por sistemas de tipos; tanto Elixir quanto Ruby introduziram sistemas de tipos, mas hoje usa principalmente Kotlin, que sintaticamente parece um “Ruby tipado”
Está usando Soketi com o pusher sdk para lidar com broadcast de eventos; o app tem uma estrutura mista de endpoints em tempo real e endpoints REST, e a carga de processamento em tempo real não é tão alta, mas se necessário pensa em separar isso em Go; também pretende adicionar recursos de colaboração em breve, e está em dúvida se faz sentido adotar Phoenix nessa situação