Lisp, cosa mi combini? Aggiungi un commento

28 marzo 2007, 8:08

Dall’ottimo libro di Paul Graham, ANSI Common Lisp, capitolo III, sezione 3:

Why Lisp Has No Pointers

[...] As conses have pointers to their elements, variables have pointers to their values.

You may have used other languages in which pointers were manipulated explicitly. In Lisp you never have to do this, because the language handles pointers for you. [...]

Ok Lisp, ti ringraziamo per questo. Spiegaci un po’ meglio.

The reason Lisp has no pointers is that every value is conceptually a pointer. When you assign a value to a variable or store it into a data structure, what gets stored is actually a pointer to the value. When you ask for the contents of the data structure or the value of the variable, Lisp returns what it points to.

Ecco perchè mi sentivo sempre un po’ a disagio con tutto quel modificare e copiare liste. Ad un certo punto del progettino in corso, avevo a disposizione (bene attenti) una lista di 5 elementi:

(mi co cre va pa)

da appaiare, ripetuta 5 volte, con il numero 25, in modo da ottenere una lista di 25 elementi (che siano lo stesso numero, è una coincidenza) in modo da ottenere una lista di 5 sottoliste così formate:

((mi 25 co 25 cre 25 va 25 pa 25) (mi 25 co 25 cre 25 va 25 pa 25) (...) ...)

per la qual cosa, all’inizio, non ho trovato di meglio che utilizzare la procedura make-list, che effettua n copie (n passato a parametro) di un dato elemento iniziale, anch’esso passato a parametro. Ma viste le affermazioni precedenti dl Graham, mi sono accorto che forse qualcosa non andava nel momento in cui è successa la seguente cosa.

Ho finalmente la mia lista di 5 liste di secondo livello, fresca fresca e pronta per essere esaminata come un ibrido tra una a-list e una p-list:

((mi pa 25 va 25 cre 25 co 25 mi 25)
(co pa 25 va 25 cre 25 co 25 mi 25)
(cre pa 25 va 25 cre 25 co 25 mi 25)
(va pa 25 va 25 cre 25 co 25 mi 25)
(pa pa 25 va 25 cre 25 co 25 mi 25))

Per inizializzare l’algoritmo di Bellman-Ford per i cammini minimi a sorgente singola, devo porre la stima di cammino minimo dalla sorgente a 0. Altrimenti l’algoritmo non parte neanche. Quindi eseguo utilizzando una buona combinazione setf/getf.

Il car della mia lista diventa

(mi pa 25 va 25 cre 25 co 25 mi 0)

E fin qui tutto bene. Controllo anche il resto della lista, per essere più tranquillo. Ecco l’amara sorpresa.

((mi pa 25 va 25 cre 25 co 25 mi 0)
(co pa 25 va 25 cre 25 co 25 mi 0)
(cre pa 25 va 25 cre 25 co 25 mi 0)
(va pa 25 va 25 cre 25 co 25 mi 0)
(pa pa 25 va 25 cre 25 co 25 mi 0))

Che diavolo è successo? Salta fuori che la make-list di cui mi sono tanto fidato, quando le viene passata una lista come argomento iniziale, copia i puntatori, quello che il Graham chiama “la struttura condivisa” della lista, piuttosto che i valori. Dopo un giorno di riflessione io, che ho un’antipatia naturale per i puntatori (ok, non programmerò mai in C) ho risolto usando le adeguate procedure per creare a-lists. Non è cosa combina Lisp, ma che sto combinando io!!