Avete “digerito” la prima parte? Ok, allora proseguiamo! Nella prima parte abbiamo parlato anche degli array, gestendoli però con alcuni semplici metodi standard. newLisp però prevede delle funzioni (di cui alcune già viste la volta scorsa) per la manipolazione di liste-array. Prima di tutto, facciamo un “brutale” copia/incolla dal manuale, e vediamo quali funzioni abbiamo a nostra disposizione:
append Appende gli array array Crea ed inizializza un array fino a 16 dimensioni array-list Converte un array in una lista array? Controlla se una espressione è un array det Ritorna il determinante di una matrice first Ritorna la prima riga di un array invert Ritorna l’inversa di una matrice last Ritorna l’ultima riga di un array mat Esegue operazioni scalari su matrici multiply Moltiplica due matrici nth Ritorna un elemento di un array rest Ritorna tutti gli elementi di un array tranne il primo setf Set (imposta) i contenuti di un array per reference slice Ritorna uno slice (una parte, un sottoinsieme) di un array sort Mette in ordine gli elementi di un array transpose Traspone una matriceAlcune note importanti:
- Gli array multidimensionali vengono gestiti come array di array.
- Quando usato in modo interattivo, gli array sono mostrati come liste, e non c’è nessun modo per distinguerli.
- Gli array possono essere non-rettangolari, ma quando vengono serializzati diventano rettangolari.
- La funzione array crea sempre array rettangolari.
E allora quando dobbiamo usare gli array? Vanno usati quando si devono gestire GRANDI quantità di dati, ad accesso casuale, i quali risultano troppo lenti per essere gestiti tramite le liste. Per inizializzare un array dobbiamo procedere in questo modo:
> (array 2 3) ((nil nil nil) (nil nil nil))
Se volessimo inserire un elemento all’interno durante la sua creazione, aggiungiamolo con una lista:
> (array 2 3 '(1))
((1 1 1) (1 1 1))
> (array 2 3 (sequence 1 6))
((1 2 3) (4 5 6))
> (array 2 3 '("X"))
(("X" "X" "X") ("X" "X" "X"))
Per inserire un valore nell’array possiamo ricorrere alla funzione setf, che inserirà il valore “by-reference” (quindi è molto veloce):
> (setq mio (array 2 3 '(".")))
(("." "." ".") ("." "." "."))
> (setf (mio 0 1) "X")
"X"
> mio
(("." "X" ".") ("." "." "."))
> (setf (mio 1 2) "Z")
"Z"
> mio
(("." "X" ".") ("." "." "Z"))
Ricordatevi che gli indici partono sempre da zero!
Possiamo anche lavorare con array in altri array:
> (setf (mio 1 0) '(A B C))
(A B C)
> mio
(("." "X" ".") ((A B C) "." "Z"))
> (setf (mio 1 ) '(X Y Z))
(X Y Z)
> mio
(("." "X" ".") (X Y Z))
Nell’ultimo caso ho sostituito un intera dimensione dell’array (in termini di contenuti) con un’altra! Ed ora guardate qui:
> (setf (mio 3 ) '(W A S D)) ERR: array index out of bounds in function setf : 3
Ho cercato di inserire un elemento in un posto inesistente, ed ho ottenuto un Out of bounds. Questo perchè la funzione (setf), lavorando per reference, deve necessariamente lavorare su elementi esistenti (non si può referenziare qualcosa che non esiste!).
Come posso estrarre i dati di una riga? Ed una cella singola? Guardate questi esempi:
> (setq mio (array 4 3 (sequence 0 11))) ((0 1 2) (3 4 5) (6 7 8 ) (9 10 11)) > (mio 1 1) 4 > (mio 1) (3 4 5) > (mio -1) ;; INDICE NEGATIVO: LEGGO L'ULTIMO ELEMENTO! (9 10 11)
Si possono anche estrarre “pezzi” di array, tramite la funzione (slice):
> (slice mio 1 2) ((3 4 5) (6 7 8))
Per essere certi di lavorare con degli array, possiamo usare la funzione (array?):
> (setq mio (array 3 2 (sequence 1 6))) ((1 2) (3 4) (5 6)) > (array? mio) true > (array? (array-list mio)) ;; CONVERTO L'ARRAY IN LISTA nil > (list? (array-list mio)) ;; CONVERTO L'ARRAY IN LISTA true
Invece se si vuole convertire una lista in un array, dobbiamo usare la funzione (flat) che si occuperà di “appiattire” la lista e darla in pasto al generatore di array:
> (setq mioArray (array 2 3 (flat lista))) ((1 2 3) (4 5 6)) > (setq mioArray (array 3 2 (flat lista))) ((1 2) (3 4) (5 6))
E’ interessante notare come questo sistema permetta di “distribuire” i valori nell’array, senza preoccuparsi della “forma” dell’array stesso nè della forma della lista.
Prima di concludere (ma la terza parte di questo workshop è già alle porte
) vediamo le funzioni (source) e (save). Esse permettono di serializzare espressioni, simboli, context, etc… e, ovviamente, array!
Facciamo subito una prova:
> (setq mioArray (array 3 2 (sequence 1 6))) ((1 2) (3 4) (5 6)) > (println (source 'mioArray)) (set 'mioArray (array 3 2 (flat '( (1 2) (3 4) (5 6))))) "(set 'mioArray (array 3 2 (flat '(\n (1 2) \n (3 4) \n (5 6)))))\n\n"
Ho aggiunto la funzione (println) per comodità di lettura. La funzione (source) genera tutto l’indispensabile per ricrare l’elemento da un’altra parte, o per salvarlo. La funzione (source) fà la stessa cosa, ma salva il codice generato direttamente su file.
Ora pensate al potenziale di queste funzioni, unite alla (net-eval).
Come dite? Non sapete cosa è la (net-eval)?! Ne parleremo in un prossimo workshop, insieme alla programmazione distribuita. Promesso!
Translate To English!
Commenti Recenti