(define (my-reverse ls)
(define (my-reverse-2 ls acc)
(if (null? ls)
acc
(my-reverse-2 (cdr ls) (cons (car ls) acc))))
(my-reverse-2 ls '()))
При этом используется переменная аккумулятора, чтобы перевернуть список, убрав первый элемент из входящего списка и поместив его в начало аккумулятора. Он скрывает функцию захвата аккумулятора и просто выставляет функцию, которая принимает список, чтобы вызывающему не приходилось передавать пустой список. Вот почему у меня есть мой реверс-2.
(my-reverse-2 '(a (b c d) e) '()); will call
(my-reverse-2 '((b c d) e) '(a)); which will call
(my-reverse-2 '(e) '((b c d) a)); which will call
(my-reverse-2 '() '(e (b c d) a)); which will return
'(e (b c d) a)
Поскольку последний вызов функции в my-reverse-2
является вызовом my-reverse-2
, и возвращаемое значение передается сразу (возвращаемое значение первого вызова равно возвращаемое значение второго вызова и т. д.) my-reverse-2
* оптимизировано для хвоста *1011*, что означает, что в стеке не останется свободного места. Так что это можно назвать списком так долго, как вам нравится.
Если вы хотите применить его к вложенным спискам, используйте что-то вроде этого:
(define (deep-reverse ls)
(define (deep-reverse-2 ls acc)
(if (null? ls)
acc
(if (list? (car ls))
(deep-reverse-2 (cdr ls) (cons (deep-reverse (car ls)) acc))
(deep-reverse-2 (cdr ls) (cons (car ls) acc)))))
(deep-reverse-2 ls '()))
Это проверяет, является ли элемент списком, прежде чем добавить его в список, и, если это так, сначала переворачивает его.
Поскольку он вызывает себя для обращения к внутреннему списку, он может обрабатывать произвольное вложение.
(deep-reverse '(a (b c d) e))
-> '(e (d c b) a)
в обратном алфавитном порядке, несмотря на наличие вложенного списка.
Оценивается так:
(deep-reverse-2 '(a (b c d) e) '()); Which calls
(deep-reverse-2 '((b c d) e) '(a))
(deep-reverse-2 '(e) (cons (deep-reverse-2 '(b c d) '()) '(a)))
(deep-reverse-2 '(e) (cons (deep-reverse-2 '(c d) '(b)) '(a)))
(deep-reverse-2 '(e) (cons (deep-reverse-2 '(d) '(c b)) '(a)))
(deep-reverse-2 '(e) (cons '(d c b) '(a)))
(deep-reverse-2 '(e) '((d c b) a))
(deep-reverse-2 '() '(e (d c b) a))
'(e (d c b) a)