Aspectos de programação

Inferência de tipos

Além da tipagem fraca ou forte, as linguagens de programação podem variar quanto à abordagem utilizada para identificar o tipo de dado de uma variável.

Outro aspecto bastante importante com relação à tipos em linguagens de programação está na abordagem adotada pela linguagem para inferência de tipos. A inferência de tipos refere-se à capacidade de uma linguagem de programação de deduzir automaticamente o tipo de uma expressão no momento da compilação (em linguagens estáticas) ou durante a execução (em linguagens dinâmicas).

🪨 Estática

Na inferência de tipos estática, o tipo de cada variável e expressão é determinado em tempo de compilação e não pode mudar ao longo do tempo de execução. Linguagens como C, Java e Rust utilizam inferência de tipos estática.

int variavel; // variavel será int sempre

Isso proporciona uma série de vantagens, como melhor desempenho em tempo de execução, menor consumo de recursos, e mais segurança no código, uma vez que muitos erros podem ser captados durante a compilação.

Por exemplo, a linguagem Rust é conhecida por sua segurança de memória, que é em grande parte garantida durante a fase de compilação através da inferência de tipos.

⚡ Dinâmica

Por outro lado, a inferência de tipos dinâmica ocorre em tempo de execução. Linguagens como Python, JavaScript e Ruby são exemplos de linguagens que adotam essa abordagem. Veja um exemplo em Python:

variavel = "ufmt"
variavel = 10

A inferência de tipos dinâmica oferece maior flexibilidade e rapidez no desenvolvimento, pois permite aos desenvolvedores escrever código sem se preocupar explicitamente com a definição de tipos.

Isso pode facilitar a prototipagem rápida e a execução de mudanças em tempo real, mas também pode levar a erros em tempo de execução que seriam evitados com a inferência de tipos estática.

Por exemplo, em JavaScript, o tipo de uma variável pode mudar ao longo de sua vida útil no código, o que pode introduzir bugs se não for devidamente gerenciado.

Vejamos um exemplo:

function calcularTotal(a, b, c) {
    return a + b + c;
}

// Exemplo de uso esperado:
console.log(calcularTotal(10, 20, 30)); // Saída esperada: 60

// Chamada com tipos misturados, potencialmente por engano:
console.log(calcularTotal(10, "20", 30)); // Saída: "102030"

Neste caso, a função calcularTotal é chamada com um array que inclui uma string ("20"). Em JavaScript, o operador + é sobrecarregado para servir tanto para soma quanto para concatenação de strings.

Quando o interpretador encontra um número seguido de uma string durante a adição, ele converte todos os números subsequentes em strings e realiza a concatenação ao invés de uma soma numérica. Isso resulta na saída inesperada de "102030".