Проблема с вашим первоначальным подходом заключается в том, что вы пытаетесь напрямую портировать императивное решение, которое даже использует передачу по ссылке для отслеживания состояния обхода.Это не сработает, первым шагом будет переосмысление решения в стиле функционального программирования.
Такие проблемы, когда мы должны отслеживать, где мы находимся во вложенной структуре, лучшерешена с использованием структуры данных stack .Я буду использовать list для реализации стека списков со следующим помощником для добавления нового элемента в самый верхний список:
(define (append-top ele stack)
(cons (append (car stack) (list ele))
(cdr stack)))
Теперь для фактического решения.Предполагая, что входной список правильно сформирован с тем же числом <
и >
и в правильном порядке (проверка ошибок не выполняется):
(define (parse-tree tokens)
(let parse ([tokens tokens] [stack '(())])
(cond [(null? tokens)
; solution is at the top of the stack, return it
(car stack)]
[(eq? (car tokens) '<)
; start new sublist at the top of the stack
(parse (cdr tokens) (cons '() stack))]
[(eq? (car tokens) '>)
; pop top element of the stack, append it to previous
; frame, continue with solution where we left it
(parse (cdr tokens) (append-top (car stack) (cdr stack)))]
[else
; add current element to top of stack
(parse (cdr tokens) (append-top (car tokens) stack))])))
Работает, как и ожидалось!
(parse-tree '(1 < 2 < 3 4 > > Z < X >))
=> '(1 (2 (3 4)) Z (X))