Rust é uma linguagem maravilhosa, estou no meu 6º ou 7º projeto com ela, 4 deles em produção, 1 lib publicada (aqui) e um jogo escrito usando a lib bevy. De fato rust é uma linguagem que consegue trazer muita produtividade quando se entende os conceitos da linguagem, mas o meu ponto preferido da linguagem é o fato de não ter null/undefined e se vc programa em rust pode pensar que o "None" seria equivalente e pode até ser, mas a forma com que a linguagem trata o "None" é bem diferente e vou fazer uma analogia aqui para tentar explicar.
Suponha que fizemos um SELECT WHERE num banco de dados usando uma linguagem qualquer, como costume salvamos esse resultado numa variável e agora essa variável se tornou o que eu carinhosamente apelidei de Variável de Shrodinger
, pois ela pode ter um resultado ou pode ter um null/undefined/None, até que seja feito algo como um "if" para verificar o conteúdo, essa variável é um mistério. Numa linguagem como JS/TS (minha linguagem de trabalho hoje) cada if é similar a abrir a caixa e olhar o que tem dentro, talvez tenha um objeto com os valores da consulta, talvez tenha um null
, se você precisa fazer várias verificações desse retorno, é como passar essa caixa pessoa por pessoa e cada 1 olha o conteúdo e passa para outra. Em rust essa verificação é diferente, rust não deixa vc abrir a caixa olhar e fechar, ele abre a caixa em cima de você e você que lide com esse resultado, ele não te devolve a caixa, isso obriga uma tratativa imediata desse resultado, a Variável de Shrodinger
deixa de existir e você precisa criar uma nova indicando explicitamente que é uma variável com conteúdo.
TypeScript:
const result = await postgres.findByEmail("any@mail.com"); // e se rolar um throw Error aqui?
if (result === null) {
return "email não encontrado";
}
return anyFunction(result); // será que essa função vai receber undefined algum dia?
Rust:
let result = postgres.findByEmail("any@mail.com").await;
match result {
Ok(value) => anyFunction(value),
Err(error) => format!("falha ao buscar usuário: {}", error)
}
Claro que é possível ter o mesmo resultado em qualquer linguagem, só que linguagens como o JS te permitem ser negligente (e muitos devs são), no exemplo anterior eu deveria usar um try/catch em volta do código mas o JS não se importa com isso...
TypeScript:
try {
const result = await postgres.findByEmail("any@mail.com");
if (result === null) {
return "email não encontrado";
}
return anyFunction(result);
} catch(error) {
return `falha ao buscar usuário: ${error.message}`
}
Rust não te deixa ser negligente tão fácilmente, vc precisa forçar a barra para fazer código ruim e mesmo que decida ir por esse caminho, quando ler o código você vai se sentir incomodado. Outro ponto é que Rust não é uma linguagem feita para entrar em estado de erro, se você programa em rust e faz o seu código com foco em executar seu binário e nunca ver ele entrar em pânico (expressão da linguagem) saiba que você entendeu e está no caminho certo.
Ah, um ultimo detalhe, realmente o cenário de rust aqui no Br está muito fraco, por conta disso estou começando um canal no YT e os primeiros vídeos já serão uma biblioteca em rust que será publicada no crates.io, vou tentar mostrar tudo, testes automatizados, documentação, processo do crates.io, baixar essa lib para usar em outros projetos, etc... e é isso, obrigado por ter lido até aqui.
Isso pelo que vejo ele ta encapsulando o retorno como Error Monad, isso vem de linguagens funcionais como Haskell. O Rust herda conceitos de Result, Maybe.. etc isso junto com as garantias que ele fornece tornam a linguagem poderosa.