(require racket/mpair)
(define (bld-mlst . args)
(list->mlist args))
(define mlst-my (bld-mlst))
mlst-my
(mappend! mlst-my (list->mlist (list 100)))
mlst-my
(define mlst-my2 (bld-mlst 2))
(mappend! mlst-my2 (list->mlist (list 100)))
mlst-my2
it will print out:
(mcons 100 '())
'()
(mcons 2 (mcons 100 '()))
(mcons 2 (mcons 100 '()))
The first and third line is just the return value of the mappend! Note the second line and fourth line! We can see that the second line is '(), which means that mappend! does not change the mlst-my! While when the mlst-my2 is not empty, the mappend! works fine.
Question:
Then How to make the mappend! to still side effect the mlist when the mlist is empty?
You can’t! The empty list is a singleton, immutable object. It has no slots (car or cdr) that you can change. But you can do this:
That is, you
set!your variable tomappend!‘s return value.To understand all that, understand how singly linked lists work. It comprises cons cells (or dotted pairs), which each have two slots (traditionally named
carandcdr). Thecarslot points to the value, and thecdrpoints to the next cons/pair.So, a list like
(1 2 3)has three conses:The way
append!works is to find the last cons (the one whosecdris pointing to()), and change itscdrto point to the list you’re appending.If your list is empty, though, it has no conses, and therefore it has nothing to change. Empty lists are always immutable.