Code Review
Compare your solutions
#|
Упражнение 3.12
В разделе 2.2.1 была введена следующая процедура для добавления одного списка к другому:
(define (append x y)
(if (null? x)
y
(cons (car x) (append (cdr x) y))))
Append порождает новый список, по очереди наращивая элементы x в начало y. Процедура append! подобна
append, но только она является не конструктором, а мутатором. Она склеивает списки вместе, изменяя
последнюю пару x так, что ее cdr становится равным y. (Вызов append! с пустым x является ошибкой.)
(define (append! x y)
(set-cdr! (last-pair x) y)
x)
Здесь last-pair — процедура, которая возвращает последнюю пару своего аргумента:
(define (last-pair x)
(if (null? (cdr x))
x
(last-pair (cdr x))))
Рассмотрим последовательность действий
(define x (list 'a 'b))
(define y (list 'c 'd))
(define z (append x y))
z
(a b c d)
(cdr x)
<ответ>
(define w (append! x y))
w
(a b c d)
(cdr x)
<ответ>
Каковы будут пропущенные <ответы>? Объясните, нарисовав стрелочные диаграммы.
|#
(#%require rackunit)
(define (append! x y)
(set-cdr! (last-pair x) y)
x)
(define (last-pair x)
(if (null? (cdr x))
x
(last-pair (cdr x))))
(define x (list 'a 'b))
(define y (list 'c 'd))
(define z (append x y))
(check-equal? z '(a b c d))
(check-equal? (cdr x) '(b))
(define w (append! x y))
(check-equal? w '(a b c d))
(check-equal? (cdr x) '(b c d))
#|
┏━━━┳━━━┓ ┏━━━┳━━━┓ ┏━━━┳━━━┓ ┏━━━┳━━━┓
x ───►┃ • ┃ • ╂──►┃ • ┃ ╱ ┃ y ───►┃ • ┃ • ╂──►┃ • ┃ ╱ ┃
┗━┿━┻━━━┛ ┗━┿━┻━━━┛ ┗━┿━┻━━━┛ ┗━┿━┻━━━┛
▼ ▼ ▼ ▼
┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓
┃ a ┃ ┃ b ┃ ┌─►┃ c ┃ ┌─►┃ d ┃
┗━━━┛ ┗━━━┛ │ ┗━━━┛ │ ┗━━━┛
▲ ▲ │ │
┏━┿━┳━━━┓ ┏━┿━┳━━━┓ ┏━┿━┳━━━┓ ┏━┿━┳━━━┓
z ───►┃ • ┃ • ╂──►┃ • ┃ • ╂──►┃ • ┃ • ╂──►┃ • ┃ ╱ ┃
┗━━━┻━━━┛ ┗━━━┻━━━┛ ┗━━━┻━━━┛ ┗━━━┻━━━┛
После (append! x y):
x y
│ │
▼ ▼
┏━━━┳━━━┓ ┏━━━┳━━━┓ ┏━━━┳━━━┓ ┏━━━┳━━━┓
w ───►┃ • ┃ • ╂──►┃ • ┃ • ╂──►┃ • ┃ • ╂──►┃ • ┃ ╱ ┃
┗━┿━┻━━━┛ ┗━┿━┻━━━┛ ┗━┿━┻━━━┛ ┗━┿━┻━━━┛
▼ ▼ ▼ ▼
┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓
┃ a ┃ ┃ b ┃ ┃ c ┃ ┃ d ┃
┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛
|#