Le liste sono molto più versatili degli array. Con gli elenchi, puoi recurse (ad es. Per mappare o piegare) facendo scorrere un elenco verso il basso. Questo non funziona per gli array; dovresti passare anche nell'indice dell'array.
Ad esempio, questa è una semplice implementazione di map
e fold
che richiede solo una lista:
(define (map1 f l)
(if (null? l) l
(cons (f (car l)) (map1 f (cdr l)))))
(define (left-fold1 f init l)
(if (null? l) init
(left-fold1 f (f (car l) init) (cdr l))))
Come lo faresti per gli array, senza dover passare un altro argomento (per l'indice)? (Ricorda, Lisp e Scheme non hanno puntatori, almeno nessuno che il codice utente possa toccare.)
Inoltre, gli elenchi possono condividere lo spazio di archiviazione, ma gli array no. Prendi questo codice Schema per esempio:
(define (x-world x)
(cons x '(world)))
(define hello-world (x-world 'hello))
(define goodbye-world (x-world 'goodbye))
Qui, hello-world
ha il valore (hello world)
e goodbye-world
ha il valore (goodbye world)
.
C'è un fatto importante, tuttavia: in molte implementazioni di Schema, la parte (world)
di entrambe le liste è effettivamente condivisa. Questa condivisione sarebbe impossibile per gli array.
Addendum: Per rispondere al punto di Compman che la ricorsione è in qualche modo "non di produzione", in Schema, tutto il ciclo / iterazione standard viene eseguito utilizzando la ricorsione della coda. Ecco una versione ricorsiva di% di map1
, ad esempio:
(define (map1 f l)
(let loop ((r '())
(l (reverse l)))
(if (null? l) r
(loop (cons (f (car l)) r) (cdr l)))))
o, ancora più semplicemente, usando left-fold1
:
(define (map1 f l)
(left-fold1 (lambda (e r) (cons (f e) r))
'() (reverse l)))
reverse
è uno schema integrato, ma la sua implementazione è ugualmente banale (e utilizza anche solo l'iterazione):
(define (reverse l)
(left-fold1 cons '() l))