Vettori
In Scheme, un vettore è un’altra struttura dati fondamentale utilizzata per raggruppare valori. A differenza degli elenchi, i vettori sono raccolte di elementi indicizzati e di dimensione fissa, che forniscono accesso casuale e aggiornamenti più rapidi. Ogni elemento in un vettore può essere di qualsiasi tipo, incluso un altro vettore. I vettori sono rappresentati utilizzando # seguito da parentesi. #(1 2 3)
Anche se i vettori e gli elenchi possono sembrare simili, hanno scopi diversi nella programmazione di Scheme:
Le liste sono più comunemente usate per operazioni ricorsive e strutture dinamiche, poiché la loro implementazione a nodo collegato consente una manipolazione efficiente del loro inizio e del loro attraversamento attraverso la scomposizione ricorsiva.
I vettori, d’altro canto, sono ottimizzati per scenari in cui è richiesto l’accesso casuale a elementi o aggiornamenti a indici specifici, rendendoli più adatti a casi d’uso come tabelle di ricerca, configurazioni a dimensione fissa o operazioni indicizzate critiche per le prestazioni.
In sostanza, le liste sono la scelta naturale per algoritmi ricorsivi e dati di dimensione dinamica, mentre i vettori brillano quando i modelli di accesso a dimensione fissa o indicizzati sono fondamentali.
Vettori semplici
(vector 1 2 3)- Crea un vettore di tre elementi:
1,2e3.
Risultato: #(1 2 3)
Accesso agli elementi vettoriali
È possibile accedere agli elementi in un vettore utilizzando la procedura vector-ref, che recupera l’elemento in un indice specificato (a partire da 0).
(define my-vector (vector 1 2 3))
(vector-ref my-vector 0) ; Retrieves the element at index 0
(vector-ref my-vector 1) ; Retrieves the element at index 1Iterazione: elaborazione di ciascun elemento in un vettore
È possibile scorrere un vettore utilizzando un ciclo o la ricorsione. Lo schema fornisce vector-length per determinare la dimensione di un vettore. Ecco un semplice ciclo per stampare ogni elemento in un vettore:
(define (print-elements vec)
(let loop ((i 0))
(if (< i (vector-length vec))
(begin
(lumi-message (number->string (vector-ref vec i))) ; Print the element
(loop (+ i 1))) ; Process the next index
(lumi-message "done")))) ; End loop- Caso base: Se l’indice
iraggiunge la lunghezza del vettore, interrompe il ciclo. - Caso ricorsivo: stampa l’elemento all’indice
i, quindi incrementai.
Esempio di utilizzo
(print-elements (vector 1 2 3))Risultato:
"1""2""3"
Risultato: “fatto”
Vettori misti
I vettori possono includere elementi di diverso tipo, tra cui stringhe, booleani, numeri, altri vettori o persino il risultato di espressioni:
(vector 42 "hello" #t (vector 1 2) (+ 3 4))Questo crea un vettore con:
- Un numero (
42) - Una stringa (
"hello") - Un valore booleano (
#t) - Un altro vettore (
#(1 2)) - Il risultato di un’espressione (
(+ 3 4), che restituisce7)
Risultato: #(42 "hello" #t #(1 2) 7)
Costruire vettori
I vettori vengono creati utilizzando vector oppure utilizzando make-vector per creare un vettore di dimensione fissa con un valore iniziale.
(make-vector 5 0)Crea un vettore di dimensione 5 con tutti gli elementi inizializzati su 0.
Risultato: #(0 0 0 0 0)
Aggiornamento dei vettori
La procedura vector-set! aggiorna un elemento in un vettore in un indice specificato.
(define my-vector (vector 1 2 3))
(vector-set! my-vector 1 42) ; Sets the second element to 42
my-vectorRisultato: #(1 42 3)
Controllo dei vettori
La procedura vector? controlla se un dato valore è un vettore.
(vector? (vector 1 2 3)) ; Checks if #(1 2 3) is a vector
(vector? 42) ; Checks if 42 is a vectorRisultato:
(vector? (vector 1 2 3))restituisce#t(vero)(vector? 42)restituisce#f(falso)
Vettori e comportamento di passaggio per riferimentoIn Scheme, i vettori sono mutabili e passati per riferimento. Ciò significa che quando passi un vettore a una funzione, la funzione può modificare direttamente il vettore originale. Qualsiasi modifica apportata al vettore all’interno della funzione si rifletterà anche all’esterno della funzione. Questo comportamento è utile per condividere e aggiornare in modo efficiente i dati tra più funzioni, ma richiede anche cautela per evitare effetti collaterali indesiderati.
Esempio: modifica di un vettore in una funzione
Ecco un esempio che dimostra come i vettori vengono passati per riferimento e modificati:
(define (modify-vector vec index new-value)
(vector-set! vec index new-value)) ; Updates the vector at the specified index
(define my-vector (vector 10 20 30))
(modify-vector my-vector 1 99) ; Modifies the second element to 99
my-vector ; The original vector is now updatedRisultato: #(10 99 30)
Spiegazione passo passo
- Crea un vettore:
my-vectorviene inizializzato con i valori10,20e30. - Passa a una funzione:
my-vectorviene passato amodify-vectorinsieme all’indice e al nuovo valore da aggiornare. - Modifica nella funzione: La procedura
vector-set!aggiorna il valore nell’indice specificato direttamente nel vettore originale. - Riflette modifiche: poiché i vettori vengono passati per riferimento, le modifiche apportate all’interno della funzione si riflettono nel vettore originale.
Implicazioni del passaggio per riferimento
- Prestazioni: Il passaggio di vettori per riferimento è efficiente perché evita di copiare strutture di grandi dimensioni.
- Effetti collaterali: prestare attenzione quando si condividono vettori tra funzioni per evitare modifiche involontarie ai dati condivisi.
Operazioni sui vettori
Scheme fornisce diverse procedure integrate per lavorare con i vettori, tra cui:
vector-length: restituisce il numero di elementi in un vettore.vector->list: converte un vettore in un elenco.list->vector: converte un elenco in un vettore.
(vector-length (vector 1 2 3)) ; Returns 3
(vector->list (vector 1 2 3)) ; Converts vector to list: (1 2 3)
(list->vector (list 1 2 3)) ; Converts list to vector: #(1 2 3)Risultato:
(vector-length (vector 1 2 3))restituisce3(vector->list (vector 1 2 3))restituisce(1 2 3)(list->vector (list 1 2 3))restituisce#(1 2 3)
Vettori nidificati
I vettori in Scheme possono contenere altri vettori come elementi, creando una struttura nidificata.
(define nested-vector (vector (vector 1 2) (vector 3 4) (vector 5)))Crea un vettore di tre elementi, ognuno dei quali è a sua volta un vettore.
Risultato: #(#(1 2) #(3 4) #(5))
Accesso ai dati annidati
Per accedere agli elementi all’interno di un vettore nidificato, utilizzare vector-ref più volte per navigare nella struttura.
Esempio: accesso agli elementi
(vector-ref nested-vector 0) ; Retrieves the first element: #(1 2)
(vector-ref (vector-ref nested-vector 0) 1) ; Retrieves the second element of the first vector: 2Riepilogo
- I Vettori nello Schema sono strutture dati indicizzate a dimensione fissa.
- Utilizzare
vectorper creare un vettore,vector-refper accedere agli elementi evector-set!per aggiornare gli elementi. - Le procedure integrate come
vector-length,vector->listelist->vectorconsentono operazioni flessibili. - I vettori nidificati consentono strutture di dati complesse e gerarchiche.