Executando verificação de segurança...
1

Muito bom cara, parabéns. Vou te dar uma dica, atualmente desenvolvo e gerencio um time que desenvolve um produto em C++. Eu recomendo a todos os integrantes a evitarem usar as autodeclarações, no caso do Rust o let, eles tem sua utilidade com certeza. Porém, eu vejo a maior vantagem de linguagens como Go, C++, C, Rust e Java é que a gente sabe qual o tipo de variável que estamos lidando, então fazer as declarações com os tipos já corretos facilita debugging.

Eu parei de estudar Rust, mas vou acompanhar seus posts

Carregando publicação patrocinada...
2

Sim essa é uma vantangem enermo, eu que sou do JS que podemos fazer uma "baguncinha" é bem diferente, estou estudando aos poucos, pois estou com altas responsabilidades agora, mas até o final do ano quero ter uma boa autonomia na linguagem, sim vou continur estudando e postando aqui. Obrigado por ajudar o post com esse feedback

1

Eu não sei se essa é uma recomendação muito razoável. C++ é uma coisa específica, o 'auto' foi um afterthought da linguagem e, apesar de ser muito utilizado (e eu diria recomendável em muitos casos), não se integra tão naturalmente. Rust por outro lado foi pensado do início pra utilizar os maiores desenvolvimentos das teorias de tipos e de inferência, é uma linguagem feita pra aproveitar ao máximo a solidez que tipagem forte permite e ao mesmo tempo a flexibilidade que utilizar a inferência de tipos permite. Se você pegar um C# ou C++ por exemplo, o tipo geralmente precede a variável, e conceitos como 'var' ou 'auto' são construídos em cima disso, em Rust o que precede é a keyword 'let' e o tipo aparece como um opcional através do ':'.

Além de que Rust possui tipos extremamente verbosos e complicados por conta de suas features de segurança e as técnicas avançadas empregadas no desenvolvimento e, justamente, a inferência permite que você não precise tipar a todo momento eles (o sistema de tipos é avançado ao ponto de que é literalmente retroativo, é algo comum ver um código que declara por exemplo um vec![] e que o tipo desse Vec é determinado pelo uso, posteriormente; o borrow checker também participa disso e códigos que seriam inválidos sendo feitos de uma determinada forma X, podem se tornar válidos se escritos de uma forma Y que garanta que as regras mais estritas não estejam sendo violadas). O próprio conceito de erros como valores por exemplo, imagine ter de escrever manualmente algo como:

let result: Result<Result<&'a Foo, std::io::Error>, tokio::time::Elapsed> = ...; 

Só pra poder passar um valor ou iterar, é insano pensar que isso seria recomendado, eu diria que torna o código muito mais confuso do que autodeclarações jamais fariam nesse caso.

Rust faz com que os tipos das variáveis sejam suficientemente explicitos sem precisar ser explicito a todo momento, ele requer que você tipe fortemente todos os parâmetros e retornos de todas as suas funções, e todo pattern matching faz uso pesado e representativo de seus tipos interiores. Ele também incentiva o uso de type hintings nos editores (o que permite ter um nível a mais de previsibilidade enquanto se está escrevendo mesmo sem escrever explicitamente os tipos). Então você geralmente vai ser capaz de saber o que X é, se X for relevante, na medida em que é utilizado.

Em debugging isso não faz praticamente nenhuma diferença, a esmagadora maioria dos debuggers vão fazer uso pesado de pretty printing e isso só importa na medida em que o compilador sabe qual o tipo, você só precisa saber dos valores (e supondo que está debugando em um editor de código, vai ter acesso a todos os tipos).

E tem uma outra vantagem clara disso que é a facilidade de refatoração. Quanto menos seu código depende de tipos estritamente, mais ele vai depender da "injeção" dos tipos feita de forma externa pelo caller, e menos você precisará se preocupar em modificar individualmente os tipos em cada única variável e cada única permutação dessa mesma variável (e.g. as funções de mapeamento monádicas). O uso de uma variável ditará as regras que ela precisa seguir na medida dos tipos aos quais ela obedece (conjunção de struct + traits), se uma função não for aplicável no contexto Y ela emitirá um erro, se um caso em um match não for coberto (devido à modificação do tipo) ele emitirá um erro, e assim em diante.

Acho que é importante respeitar as filosofias de cada linguagem ao invés de tentar encaixar todas em uma caixa com base em percepções específicas do que você se acostumou como sendo mais razoável, em linguagens funcionais como OCaml por exemplo você raramente sequer usaria tipos explícitos (mesmo nas declarações das funções, e isso considerando que é uma linguagem com tipagem extremamente forte), Rust tem seus momentos onde faz mais sentido usar a inferência, e outros onde não faz, e linguagens como C++, C# ou Java tem outros (Java por exemplo não tinha suporte a 'var' até a versão 10, enquanto que Kotlin [que roda também na JVM] tinha desde seu começo suporte nativo e bastante sólido à inferência de tipos, e seu uso não é desrecomendado de modo algum, é um dos motivos pra eu preferir pessoalmente Kotlin à Java).

Enfim, esses são meus 2¢.