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

Nim: funzioni e procedure

Nim: analizziamo il ruolo di funzioni e procedure nel linguaggio, impariamo a definirle e ad utilizzarle nelle applicazioni
Nim: analizziamo il ruolo di funzioni e procedure nel linguaggio, impariamo a definirle e ad utilizzarle nelle applicazioni
Link copiato negli appunti

In Nim, le funzioni e le procedure rappresentano elementi fondamentali per l'organizzazione e la gestione del codice. Grazie a questi costrutti, possiamo suddividere i nostri programmi in blocchi più piccoli e riutilizzabili, facilitando la manutenzione e la comprensione del codice stesso. La principale differenza tra funzioni e procedure risiede nel fatto che le funzioni restituiscono un valore, mentre le procedure no. Tuttavia, in molti casi pratici, le procedure possono essere utilizzate come se fossero funzioni.

Definizione e chiamata di funzioni in Nim

Definire una funzione in Nim è un'operazione semplice che richiede l'uso della parola chiave proc, seguita dal nome della funzione, dagli argomenti (se presenti) e dal tipo di ritorno (se presente). Analizziamo più nel dettaglio un esempio di funzione che somma due numeri interi:

proc somma(a: int, b: int): int =
  return a + b

In questa definizione, proc indica che stiamo dichiarando una funzione o una procedura. Il nome della funzione è somma, e accetta due argomenti di tipo int chiamati a e b. Il tipo di ritorno della funzione è int, indicato dopo i due punti :. La funzione restituisce la somma dei due argomenti utilizzando la parola chiave return.

La chiamata di una funzione avviene semplicemente utilizzando il nome della funzione seguito dagli argomenti tra parentesi:

let risultato = somma(3, 4)
echo risultato  # Output: 7

In questo esempio, somma(3, 4) chiama la funzione somma con i valori 3 e 4 come argomenti. Il risultato della funzione viene assegnato alla variabile risultato, che viene poi stampata a schermo utilizzando echo

Passaggio di argomenti

Il passaggio di argomenti in Nim può avvenire per valore o per riferimento. Per impostazione predefinita, gli argomenti vengono passati per valore. Questo significa che viene passata una copia dell'argomento alla funzione, e le modifiche apportate all'interno della funzione non influenzano la variabile originale. Consideriamo l'esempio seguente:

proc quadrato(x: int): int =
  return x * x
var numero = 5
let risultato = quadrato(numero)
echo risultato  # Output: 25
echo numero     # Output: 5

In questo caso, la variabile numero mantiene il suo valore originale di 5, anche dopo la chiamata alla funzione quadrato, che restituisce 25.

Se vogliamo passare un argomento per riferimento, usiamo la parola chiave var. In questo modo, la funzione riceve un puntatore all'oggetto originale e le modifiche apportate all'interno della funzione influenzano la variabile originale:

proc quadrato( x: var int) =
  x = x * x
var numero = 5
quadrato(numero)
echo numero     # Output: 25

In Nim, una procedura non deve necessariamente usare la parola chiave return per restituire un valore, specialmente se il suo scopo principale è di modificare le variabili passate per riferimento (come in questo caso). Se una procedura deve restituire un valore, può farlo utilizzando return, ma non è obbligatorio se il risultato è implicito o se la procedura modifica direttamente i parametri passati per riferimento. In questo caso, dato che non stiamo restituendo nessun valore, vediamo che dopo le parentesi della dichiarazione della procedura abbiamo semplicemente il simbolo =. Quindi, invece di:

proc quadrato(x: int): int =

che restituisce un int, abbiamo:

proc quadrato(x: int) =

che non restituisce nulla. Un altro esempio di passaggio per riferimento è il seguente:

proc modifica(x: var int) =
  x = 10
var x = 2
modifica x
echo x  # 10

Valori di Ritorno

Le funzioni in Nim possono restituire un valore utilizzando la parola chiave return. Tuttavia, se una funzione è composta da una singola espressione, possiamo omettere return e il valore di quell'espressione sarà automaticamente il valore di ritorno della funzione. Vediamo un esempio:

proc moltiplica(a: int, b: int): int =
  a * b  # `return` è implicito
let prodotto = moltiplica(3, 4)
echo prodotto  # Output: 12

In questo caso, la funzione moltiplica restituisce implicitamente il prodotto dei due argomenti, senza l'uso esplicito della parola chiave return.

Nim supporta anche il ritorno di tuple, permettendoci di restituire più valori da una funzione. Questo è particolarmente utile quando vogliamo restituire risultati multipli senza dover definire nuove strutture dati. Consideriamo l'esempio seguente:

proc divMod(a: int, b: int): (int, int) =
  (a div b, a mod b)
let (quoziente, resto) = divMod(10, 3)
echo quoziente  # Output: 3
echo resto      # Output: 1

In questo esempio, la funzione divMod restituisce una tupla contenente il quoziente e il resto della divisione di a per b. I valori restituiti vengono assegnati alle variabili quoziente e resto rispettivamente.

Funzioni ricorsive in Nim

Le funzioni ricorsive sono quelle che si chiamano da sole, permettendo di risolvere problemi complessi suddividendoli in problemi più semplici dello stesso tipo. La ricorsione è un concetto fondamentale in molti algoritmi e strutture dati. Un esempio classico di funzione ricorsiva è il calcolo del fattoriale di un numero:

proc fattoriale(n: int): int =
  if n == 0:
    return 1
  else:
    return n * fattoriale(n - 1)
let risultato = fattoriale(5)
echo risultato  # Output: 120

Nella funzione fattoriale, se n è zero, restituiamo 1. Altrimenti, restituiamo n moltiplicato per il fattoriale di n-1, chiamando la funzione stessa. La funzione continua a chiamarsi fino a raggiungere il caso base, n == 0.

Le funzioni ricorsive possono anche essere utilizzate per esplorare strutture dati come alberi e grafi. Consideriamo un esempio di traversamento di un albero binario:

type
  Node = ref object
    data: int
    left, right: Node
proc inOrderTraversal(n: Node) =
  if n != nil:
    inOrderTraversal(n.left)
    echo n.data
    inOrderTraversal(n.right)
# Creiamo un semplice albero binario
let root = Node(data: 1, left: Node(data: 2), right: Node(data: 3))
inOrderTraversal(root)  # Output: 2 1 3

In questo esempio, la funzione inOrderTraversal visita ogni nodo di un albero binario in ordine in-order. Se il nodo corrente non è nullo, la funzione chiama se stessa sul sottoalbero sinistro, poi stampa il valore del nodo corrente e infine chiama se stessa sul sottoalbero destro.

Conclusioni

Abbiamo esplorato in dettaglio le funzioni e le procedure in Nim, comprendendo come queste strutture ci permettano di organizzare il codice in modo chiaro e modulare. Esse sono comuni anche ad altri linguaggi come per esempio Java dove vengono proposte come metodi.

In particolare, abbiamo imparato a definire funzioni usando la parola chiave proc, a specificare gli argomenti e il tipo di ritorno. La chiamata delle funzioni è semplice e diretta, rendendo il codice leggibile e facile da seguire.

Abbiamo discusso poi il passaggio di argomenti per valore e per riferimento. Passare argomenti per valore significa che la funzione lavora su copie degli argomenti originali, mentre passare per riferimento permette alla funzione di modificare direttamente i valori originali. Questo è cruciale per la gestione efficiente della memoria e delle prestazioni.

Le funzioni in Nim possono restituire valori utilizzando la parola chiave return, ma possono anche implicare il valore di ritorno se composte da una singola espressione.

È stato inoltre esplorato anche il ritorno di tuple, che permette di restituire più valori senza dover creare strutture dati aggiuntive. Nella prossima lezione ci occuperemo dei tipi di dato avanzati presente in Nim.

Ti consigliamo anche