Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Le funzioni di Rust

Analizziamo le funzioni in Rust, impariamo a crearne una e scopriamo il ruolo di argomenti e valori di ritorno
Analizziamo le funzioni in Rust, impariamo a crearne una e scopriamo il ruolo di argomenti e valori di ritorno
Link copiato negli appunti

I gangli operativi di un programma Rust sono le funzioni costituite da un blocco di istruzioni delimitato da parentesi graffe e associato ad un nome simbolico introdotto, in questo linguaggio, dalla parola chiave fn.

Sin dalle prime righe di codice che scriviamo in Rust abbiamo a che fare con le funzioni. Sappiamo infatti che l'esecuzione di un intero programma Rust inizia da un singolo entry point, rappresentato dalla funzione main:

fn main(){
    // codice da eseguire
}

Come vediamo, main

La nostra prima funzione

Al di là del main, scriveremo tantissime funzioni e la nostra bravura come programmatori consisterà proprio nel saper organizzare la logica del programma articolandola in funzioni e nel modo in cui esse verranno attivate. Impariamo quindi a scrivere questi costrutti con un esempio. Supponiamo di voler fare in modo che il nostro hello world, non si occupi di stampare il messaggio all'interno del main ma che, per farlo, invochi una funzione ulteriore:

fn saluta(){
    println!("Ciao mondo! (stampato da una funzione)");
}

fn main() {
    println!("Avvio del programma...");
    saluta();
    println!("...fine del programma");
}

Abbiamo definito una funzione esterna al main saluta println main saluta()

Questa è la scrittura della nostra prima funzione, diversa dal main, che espone il tipico flusso di lavoro che affronteremo con questi costrutti: una funzione viene definita, viene invocata, svolge le operazioni per cui è programmata dopodiché restituisce il controllo al chiamante.

Serve però saper integrare questo assetto con altri dettagli, in primis l'uso di argomenti e valori di ritorno.

Argomenti e valori di ritorno

Le funzioni costituiscono dei "blocchi" operativi che spesso hanno bisogno di lavorare su valori immessi in input e restituiscono dei risultati. La funzione saluta dell'esempio precedente non necessitava dei primi né restituiva i secondi ma quando una funzione svolge delle elaborazioni deve poter specificare entrambi.

Supponiamo che ci serva una funzione in grado di ricevere due numeri in ingresso e restituirne la somma. In pratica una funzione che riceva come argomenti di lavoro due interi, diciamo di tipo i32, e prometta di restituire come risultato un valore dello stesso tipo. Ecco il codice che potremmo utilizzare:

fn somma(op1:i32, op2:i32) -> i32{
    return op1+op2;
}

La struttura ricalca quello che già sappiamo delle funzioni ma fanno il loro ingresso tre elementi che permettono di gestire il flusso dei dati:

  • tra le parentesi tonde, appaiono gli argomenti op1:i32, op2:i32 op1 op2 i32
  • l'operatore freccia (-> risultato
  • la parola chiave return

Provando il codice poniamo nel main una chiamata che effettivamente attiverà la funzione:

fn somma(op1:i32, op2:i32) -> i32{
    return op1+op2;
}

fn main() {
     println!("Somma tra due numeri: {}", somma(10, 12));
}

Con l'espressione somma(10,12)

Somma tra due numeri: 22

Rust permette di omettere la parola chiave return somma

fn somma(op1:i32, op2:i32) -> i32{
    op1+op2
}
fn main() {
     println!("Somma tra due numeri: {}", somma(10, 12));
}

In questa forma il programma restituirà lo stesso output di prima ma si faccia attenzione che non va usato il punto e virgola alla fine dell'espressione all'interno della funzione.

Ricorsione nelle funzioni di Rust

Anche in Rust potremo utilizzare la ricorsione ovvero la proprietà di una funzione di restituire un risultato costruito invocando più volte sé stessa. Un tipico esempio è quello del calcolo di un fattoriale che equivale a moltiplicare un numero intero per tutti i valori che lo precedono. Questo può essere calcolato, senza cicli, richiamando la medesima funzione più volte, applicata di volta in volta al valore precedente. Nell'esempio che segue, scriviamo la funzione fattoriale e nel main attiviamo un ciclo che mostrerà i fattoriali di tutti i numeri interi fino a 10:

fn fattoriale(valore : i128) -> i128{

    if valore<=1 {
        return 1;
    }
    valore * fattoriale(valore-1)
}

fn main() {
      for i in 2..=10 {
          println!("Fattoriale di {}: {}", i, fattoriale(i));
      }

}

Il risultato che si ottiene è:

Fattoriale di 2: 2
Fattoriale di 3: 6
Fattoriale di 4: 24
Fattoriale di 5: 120
Fattoriale di 6: 720
Fattoriale di 7: 5040
Fattoriale di 8: 40320
Fattoriale di 9: 362880
Fattoriale di 10: 3628800

Tutto ha funzionato e, come possiamo vedere, nella funzione fattoriale return

Ti consigliamo anche