Like most Schemes, Racket
provides a 'reverse' procedure.
Your approach to reversing a list is basically sound, but you are performing some unnecessary steps (and it would be better if it handled the case of an empty list).
The traditional Scheme way of defining a function that loops through a list and returns some result (such as the reversed list) is to define an iteration function which accepts one additional argument, the result to be returned. Each iteration through the list, the result gets updated based upon the first item in the list and then the iteration repeats with the remainder of the list..
Code: Select all
(define (reverse-list-iter lis result)
(if (null? lis)
result
(reverse-list-iter (cdr lis) (cons (car lis) result)) ))
Your function will then call this iteration function with an appropriate initial value for the result (in your case, the empty list).
Code: Select all
(define (reverse-list lis)
(reverse-list-iter lis '()) )
Of course, it makes sense to nest the definition of the iteration function within your function, to keep things organized and to avoid cluttering up your namespace.
Code: Select all
(define (reverse-list lis)
(define (iter lis result)
(if (null? lis)
result
(iter (cdr lis) (cons (car lis) result)) ))
(iter lis '()) )
And by having your reverse function handle an empty list (returning an empty list), your "last item removal" function becomes almost trivial. (And of course, you could just use the standard 'reverse' function instead.)
Code: Select all
(define (butlast lis)
(if (null? lis)
'()
(reverse-list (cdr (reverse-list lis))) ))