I need to create a program that will reverse a list destructively. For example lets say..
scm> (define L (list 1 2 3 4))
scm> (reverse! L)
(4 3 2 1)
scm> L
(1)
Where L becomes the last element of the reversed list. I know I am supposed to use set-cdr! somehow but cannot figure out how to implement it.
So I was wondering how to do this today since I needed it for a test. For every list with more than 1 element I keep the first
cons
in the argument as the first in the result. I make a fresh cons to hold the new last value with a dummy value, then I reverse the link for elements 2..n-1. In the end i set the car of the firstcons
and the newlast
. The result is the result of the lastset-cdr!
.Example:
Because this looks like homework, I can't give you a straight answer. I'll show you the general structure of the solution, so you can figure out the details and fill-in the blanks:
In the above code:
let
for simplicity, given that another parameter is neededacc
parameter is defined, to serve as the accumulator for the reversed listNow, for the recursive step:
<?1?>
we need to obtain a reference to the rest of the list and save it, given that we're going to modify it(set-cdr! <?2?> <?3?>)
. You'll have to set the next element of the current list to the previously accumulated, reversed listNotice that in the end, the
lst
reference got modified in-place and now is pointing to the last element of the list. If you needlst
to point to the reversed list, then simply do this:The procedure described reverses a list destructively and doesn't create a new list (no
cons
operations are used.)You should read the section on mutators from the The Scheme Programming Language book. Also, look into the the
case
function in Scheme. Essentially, you can use theset!
function to fundamentally change a definition and also give another output.How de fella UCB.
here is my solution for your HilAcke.
then after defined you can check with the usual