开发者

mappend! can't append element to the list if the list is empty?

开发者 https://www.devze.com 2023-04-03 15:09 出处:网络
(require racket/mpair) (define (bld-mlst . args) (list->mlist args)) (define mlst-my (bld-mlst)) mlst-my
(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 1开发者_JS百科00 '())
'()
(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:

(set! mlst-my (mappend! mlst-my (list->mlist (list 100))))

That is, you set! your variable to mappend!'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 car and cdr). The car slot points to the value, and the cdr points to the next cons/pair.

So, a list like (1 2 3) has three conses:

#0=(1 . #1#)
#1=(2 . #2#)
#2=(3 . ())

The way append! works is to find the last cons (the one whose cdr is pointing to ()), and change its cdr to 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.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号