Sto provando a scrivere un'implementazione ricorsiva della funzione take-while
in Scheme (ma questo esercizio può essere fatto anche in un'altra lingua). Il mio primo tentativo è stato
(define (take-while p xs)
(if (or (null? xs)
(not (p (car xs))))
'()
(cons (car xs) (take-while p (cdr xs)))))
che funziona correttamente ma non è ricorsivo in coda. Il mio prossimo tentativo è stato
(define (take-while-tr p xs)
(let loop ((acc '())
(ys xs))
(if (or (null? ys)
(not (p (car ys))))
(reverse acc)
(loop (cons (car ys) acc) (cdr ys)))))
che è ricorsivo di coda ma ha bisogno di una chiamata a reverse
come ultimo passaggio per restituire l'elenco dei risultati nell'ordine corretto.
Non riesco a trovare una soluzione che
- è coda-ricorsivo,
- non usa
reverse
, - utilizza solo elenchi come struttura dei dati (utilizzando una struttura dati funzionale come Haskell's sequenza che consente di aggiungere elementi non è un'opzione),
- ha una complessità lineare nella dimensione del prefisso, o almeno non ha una complessità quadratica (grazie a delnan per averlo indicato).
Esiste una soluzione alternativa che soddisfi tutte le proprietà di cui sopra? La mia intuizione mi dice che è impossibile accumulare il prefisso di una lista in modo ricorsivo in coda mantenendo l'ordine originale tra gli elementi (cioè senza la necessità di usare la retromarcia per regolare il risultato) ma non sono in grado di dimostrarlo .
Nota
La soluzione che utilizza reverse
soddisfa le condizioni 1, 3, 4.