Код Ревью
Сравни свои решения
#| Для этого упражнения нет проверок.
Любое решение будет считаться успешным ответом. |#
;; 1. Первая версия:
(define (square-list items)
(define (iter things answer)
(if (null? things)
answer
(iter (cdr things)
(cons (square (car things))
answer))))
(iter items nil))
В этой версии iter формирует список в обратном порядке, потому что cons добавляет новые элементы в начало answer.
Пример выполнения для (square-list '(1 2 3 4)):
(iter '(1 2 3 4) '())
(iter '(2 3 4) '(1^2)) → '(1)
(iter '(3 4) '(3^2 1)) → '(4 1)
(iter '(4) '(9 4 1)) → '(16 9 4 1)
(iter '() '(16 9 4 1)) → возврат результата
Результат: '(16 9 4 1), но мы ожидали '(1 4 9 16).
;; 2. Вторая версия:
(define (square-list items)
(define (iter things answer)
(if (null? things)
answer
(iter (cdr things)
(cons answer
(square (car things))))))
(iter items nil))
Здесь cons вызывается как (cons answer (square (car things))). Проблема в том, что cons принимает элемент и список, но answer — это уже список. Поэтому cons создаёт вложенные списки, а не обычный список чисел.
Пример выполнения (square-list '(1 2 3 4)):
(iter '(1 2 3 4) '())
(iter '(2 3 4) '(() 1))
(iter '(3 4) '((() 1) 4))
(iter '(4) '(((()) 1) 9))
(iter '() '((((()) 1) 9) 16))
Результат: ((((()) 1) 9) 16), что явно не то, что нам нужно.
Как исправить?
Чтобы получить результат в правильном порядке, можно использовать append, но это неэффективно. Лучше перейти на хвостовую рекурсию с аккумулятором и затем перевернуть список:
(define (square-list items)
(define (iter things answer)
(if (null? things)
(reverse answer) ; Переворачиваем список в конце
(iter (cdr things)
(cons (square (car things)) answer))))
(iter items nil))
Теперь порядок сохраняется правильно, и процесс остаётся итеративным.