Funções em Rust: Os Blocos de Construção do Código
Funções são essenciais em Rust. Elas são declaradas com a palavra-chave fn e servem como a estrutura principal para o código, sendo a função main o ponto de entrada de qualquer programa.
Rust utiliza o padrão snake case para nomes de funções e variáveis, onde todas as letras são minúsculas e as palavras são separadas por sublinhados (ex: calcular_total).
Aqui está um exemplo simples de definição e chamada de função:
fn main() {
println!("Início do programa.");
saudacao();
// A ordem de execução segue a ordem das chamadas dentro de `main`.
}
fn saudacao() {
println!("Olá, Rustacean!");
// A função é definida usando `fn nome_funcao() { ... }`.
}
Ao rodar, o código exibe:
Início do programa.
Olá, Rustacean!
Parâmetros em Funções
As funções podem receber parâmetros (valores de entrada) que são definidos em sua assinatura. Em Rust, é obrigatório declarar o tipo de cada parâmetro.
Isso é fundamental: informar o tipo ajuda o compilador a garantir que o código esteja correto e fornece mensagens de erro muito mais claras.
Exemplo com um parâmetro:
fn main() {
imprimir_numero(10);
// 10 é o argumento passado para o parâmetro `x`.
}
fn imprimir_numero(x: i32) {
// Declara o parâmetro 'x' como um inteiro de 32 bits (i32).
println!("O número fornecido é: {x}");
}
Exemplo com múltiplos parâmetros:
Quando há mais de um, separe-os por vírgula e declare o tipo de cada um.
fn main() {
calcular_area(2.5, 4.0);
}
fn calcular_area(base: f64, altura: f64) {
// Ambos os parâmetros são do tipo 'f64' (ponto flutuante).
let area = base * altura;
println!("A área do retângulo é: {area}");
}
Statements e Expressions
O corpo das funções em Rust é composto por statements (declarações) e expressions (expressões), e entender a diferença é crucial:
- Expressions (Expressões): Avaliam para um valor resultante. Elas formam a maior parte do código. Exemplos: uma operação matemática (
1 + 2), a chamada de uma função, ou um bloco de código entre chaves.
Statements (Declarações): São instruções que executam uma ação e não retornam valor. Exemplos: definir uma variável com let ou a própria definição de uma função.
let y = 6; é uma declaração.Blocos de Código como Expressões:
Um bloco de código {...} pode ser uma expressão, e o valor retornado é o da última linha, desde que ela não termine com ponto e vírgula.
fn main() {
let z = {
let a = 10; // Statement
a + 5 // Expression (retorna o valor 15)
};
println!("O valor de Z é: {z}"); // Saída: 15
}
Funções com Retorno de Valor
Funções podem devolver um valor para quem as chamou. Para isso:
- Declare o tipo de retorno na assinatura após uma seta (
->). - O valor retornado implicitamente é o da última expression no corpo da função (sem ponto e vírgula).
Você pode usar explicitamente a palavra-chave return, mas a prática comum em Rust é usar a expressão final.
Exemplo de Retorno:
fn main() {
let resultado = dobro(8);
println!("O dobro é: {resultado}"); // Saída: 16
}
fn dobro(numero: i32) -> i32 {
// Declara que a função retorna um i32.
numero * 2 // Expressão final (SEM ponto e vírgula)
}
Cuidado com o Ponto e Vírgula
Se você colocar um ponto e vírgula na expressão final, ela se transforma em um statement e não retorna um valor. O compilador Rust representa a ausência de valor com o tipo unit (()), o que gera um erro se a função esperava, por exemplo, um i32:
fn erro_de_retorno(valor: i32) -> i32 {
valor + 1; // Com ponto e vírgula, isso se torna um Statement.
// O Rust retorna implicitamente '()' (unit), não 'i32'.
}
// Isso causaria um erro de 'mismatched types' (tipos incompatíveis).