O Swift tem uma coexistência peculiar: é uma linguagem em que iniciantes começam no Playgrounds com uma linha, print("Hello"), enquanto a biblioteca padrão da mesma linguagem mistura genéricos e macros. Um app de educação em programação para crianças do ensino fundamental (Swift Playgrounds) e código de sistemas em nível de compilador compartilham a mesma sintaxe.
Normalmente, as linguagens escolhem um dos lados: ser fáceis de aprender (como Python) ou poderosas (como C++). O Swift declarou que teria os dois, e o princípio de design que tornou isso possível tem um nome: divulgação progressiva, Progressive Disclosure.
Este artigo é a segunda parte da série sobre a filosofia do Swift. Se Safe, Fast e Expressive, tratados na primeira parte, são a filosofia de “o que construir”, Progressive Disclosure é a filosofia de “em que ordem mostrar isso”.
O que é divulgação progressiva — Esconder até ser necessário
Progressive Disclosure é originalmente um termo de design de UI. Ele mostra primeiro apenas os recursos usados com frequência e esconde os avançados atrás de “Mais”, para não sobrecarregar iniciantes. Como um app de câmera que exibe apenas o botão do obturador em destaque e esconde ISO e velocidade do obturador no modo Pro.
A equipe do Swift aplicou esse princípio à sintaxe da linguagem. Ele também é um objetivo declarado oficialmente. Chris Lattner descreveu o Swift em várias entrevistas como “uma linguagem com divulgação progressiva da complexidade (progressive disclosure of complexity)”. Ainda hoje, as revisões de propostas do Swift Evolution perguntam se determinada sintaxe prejudica o progressive disclosure.
Em uma frase, o princípio é:
Um conceito que ainda não foi aprendido não deve aparecer no código de quem ainda não o conhece.
Não é simplesmente “também existem recursos fáceis”. É uma exigência muito mais forte: enquanto a pessoa escreve código simples, conceitos difíceis nem sequer devem entrar em seu campo de visão.
Comparando Hello World — Contando os personagens
Basta comparar o Hello World para ver o que esse princípio realmente muda.
// Java (11 anterior)
public class Main {
public static void main(String[] args) {
System.out.println("Hello, world!");
}
}
Para entender completamente essas cinco linhas, é preciso conhecer classes, controle de acesso, static, métodos, arrays e o objeto de saída padrão. O código do primeiro dia tem seis personagens. Ao professor resta dizer: “Memorize por enquanto; explico depois.”
// Swift
print("Hello, world!")
No Swift, é uma linha. Você pode escrever código executável diretamente no nível superior do arquivo, sem ponto e vírgula nem import. Há apenas um personagem: uma chamada de função. Não é preciso “memorizar por enquanto”.
Esse é o ponto central. O Swift também tem classes, controle de acesso e static. Eles apenas não aparecem neste código. Os conceitos não estão ausentes; ficam invisíveis para quem ainda não precisa deles.
Várias camadas da mesma função — A sintaxe se abre em degraus
Ao analisar a sintaxe do Swift, você descobre que a mesma função se sobrepõe em várias camadas de dificuldade. Veja alguns exemplos representativos.
Função → closure → closure abreviada. Para ordenar um array, no começo basta passar uma função nomeada.
func byLength(_ a: String, _ b: String) -> Bool {
a.count < b.count
}
names.sorted(by: byLength)
Depois de aprender closures, você pode escrevê-las inline.
names.sorted(by: { a, b in a.count < b.count })
Quando aprende a sintaxe abreviada, pode reduzir para isto.
names.sorted { $0.count < $1.count }
Os três códigos fazem exatamente a mesma coisa. É possível ordenar desde o primeiro dia sem conhecer trailing closures nem $0, e depois escrever de forma mais concisa quando aprender esses recursos. Aprender uma nova camada é uma recompensa, não uma exigência.
Inferência de tipos → tipos explícitos. Você começa com let age = 30, e a anotação de tipo só aparece quando se torna necessária, como ao definir precisão ou uma fronteira de API. Você não é obrigado a escrever let age: Int = 30 desde o início.
init memberwise automático → init personalizado. Em um struct, o compilador gera o inicializador mesmo que você não escreva código de inicialização. Só é preciso aprender a sintaxe de init quando surge a necessidade de lógica de inicialização.
Ignorar erros → try? → do-catch → throws tipado. O tratamento de erros também oferece uma escada que você pode subir conforme seu nível de interesse.
Complexidade fora do campo de visão — O que funciona nos bastidores
Mais impressionante que a escada da sintaxe é a estrutura em que recursos avançados sustentam o código iniciante nos bastidores.
A declaração real daquele print("Hello")print é assim.
func print(
_ items: Any...,
separator: String = " ",
terminator: String = "\n"
)
Argumentos variádicos, parâmetros padrão e o tipo Any. Três conceitos que iniciantes ainda não conhecem aparecem na declaração, mas quem chama não precisa saber nenhum deles. O recurso avançado de parâmetros padrão torna o uso para iniciantes simples. Recursos avançados são usados para absorver complexidade, não para adicioná-la.
A interpolação de strings ("이름: \(name)") segue a mesma estrutura. Para quem usa, é uma sintaxe básica aprendida na primeira semana, mas por baixo existe uma camada completa de personalização chamada protocolo ExpressibleByStringInterpolation. Graças a ela, o Text do SwiftUI aceita até imagens e formatação de datas por interpolação de strings. 99% dos usuários a utilizam bem por toda a vida sem saber que o protocolo existe. Só autores de bibliotecas precisam abrir essa porta.
SwiftUI é a síntese desse princípio.
struct ContentView: View {
var body: some View {
Text("Hello")
}
}
Sob esse código curto estão tipos opacos (some), resultBuilder e tipos associados de protocolos. Todos estão entre os recursos mais difíceis do Swift, mas quem cria uma UI pela primeira vez consegue exibir uma tela sem sequer saber que eles existem. A pergunta “O que é some View?” normalmente só aparece meses depois; aí é hora de aprender.
O caso oposto — O que acontece sem esse princípio
O valor do princípio fica claro quando o comparamos com linguagens que não o possuem.
Ao aprender C++, conceitos de memória como ponteiros, referências e construtores de cópia são expostos na superfície da sintaxe desde a primeira semana. Não estão escondidos: são portões inevitáveis. Para garantir segurança, Rust exige propriedade e lifetimes de todos os usuários logo de início. É um design excelente, mas, pelo critério de “quantos conceitos são necessários para escrever o primeiro programa”, está no extremo oposto.
O interessante é que outras linguagens avançaram na mesma direção do Swift. O Java introduziu no 21 classes implícitas executáveis apenas com void main() (JEP 445, uma proposta de melhoria do Java), e o C# adicionou instruções de nível superior. A justificativa é a mesma: remover a cerimônia do primeiro código do iniciante. Linguagens de gerações anteriores levaram uma década para alcançar o que o Swift adotou como padrão em 2014.
Também há críticas — Onde a escada desmorona
Para ser justo, não existe apenas a avaliação de que o Swift seguiu esse princípio perfeitamente.
A principal crítica é que os degraus intermediários ficaram mais íngremes à medida que a linguagem cresceu. A introdução é fácil, mas, ao passar para código de produção ou de biblioteca, restrições genéricas, a distinção entre some e any e anotações Sendable surgem todas de uma vez. A strict concurrency do Swift 6 é especialmente criticada por entrar em conflito direto com progressive disclosure, pois “exibe erros de compilação no código de quem ainda não aprendeu concorrência”. Até Chris Lattner já afirmou que o Swift ficou mais complexo.
A equipe do Swift reconhece essa tensão. Várias propostas posteriores ao Swift 6.1 (opções de isolamento padrão de actor, main sem nome e outras) mostram uma direção de “não encontrar conceitos de concorrência antes de precisar deles”. É mais correto ver o princípio não como algo concluído, mas como um valor que a equipe ainda luta para preservar.
Lições para profissionais — Um critério para design de API
Esse princípio não se aplica apenas a usuários da linguagem. Ele é um critério de design que se aplica diretamente às funções e aos módulos que criamos todos os dias.
Torne casos comuns gratuitos com parâmetros padrão. Como o separator do print, esconda atrás de valores padrão as opções com as quais 90% dos chamadores não se importam. Compare com uma API que exige um objeto de configuração inteiro.
Um ponto de entrada simples; overloads avançados ficam atrás. URLSession é um bom exemplo. data(from: url) Você pode começar com uma linha, enquanto uma camada separada se abre para quem precisa de delegates e configuração.
Se conceitos desconhecidos vazam para o ponto de chamada, isso é um sinal de design. Se usar minha biblioteca exige ler uma assinatura genérica, a complexidade que deveria ter sido absorvida está vazando. Assim como o print mantém o ponto de chamada simples mesmo usando argumentos variádicos, a complexidade deve ser engolida pela declaração.
Em resumo, uma boa API não é uma API com poucos recursos, mas uma API em que os recursos que você ainda não aprendeu ficam invisíveis.
Resumo
- Progressive Disclosure é o princípio oficial de design do Swift: “fazer com que conceitos ainda não aprendidos não apareçam no código”.
- O Hello World de uma linha com print, a inferência de tipos, o init automático e a escada de closures abreviadas são todos frutos desse princípio.
- Recursos avançados (parâmetros padrão, resultBuilder e o protocolo de interpolação de strings) foram projetados para absorver a complexidade do código iniciante.
- Há pontos em que o princípio vacilou, como na concorrência do Swift 6, e a equipe da linguagem ainda está consertando a escada.
- Podemos aplicar o mesmo critério às nossas APIs: usos comuns em uma linha, e a complexidade absorvida pelas declarações.
A próxima parte será a terceira história sobre filosofia. Por que a biblioteca padrão do Swift é quase toda feita de structs? Vamos abordar a prioridade dos tipos por valor.
Continue lendo
- [Filosofia do Swift #3] Por que o Swift é todo feito de structs? Guia completo da prioridade dos tipos por valor
- [Filosofia do Swift #4] O que é SE-0296? Como nasce a sintaxe do Swift: guia completo do Swift Evolution
- [Swift intermediário #1] Guia completo do Swift ARC: escolha weak vs unowned pela relação de lifetime

![Imagem de capa de [Filosofia do Swift #2] O que é Progressive Disclosure?](/assets/images/posts/290b697a-f011-4cb7-8331-0a439b666fcd/1.jpg)