Недавно я впервые возился со схемой в течение многих лет. Я использую repl.it, чтобы поиграть немного. Я написал эту основную функцию, чтобы взять список и вернуть двусвязный список. Каждая ячейка списка представляет собой пару, автомобиль которой является элементом списка, а cdr - пара с предыдущим элементом в автомобиле и следующий элемент в cdr. Первый и последний элементы имеют нуль как предыдущий и следующий элементы соответственно. Я написал эту функцию как хвост рекурсивный. Теперь я знаю, что на самом деле схема имеет петлевый синтаксис, но я был под впечатлением, когда писал, что единственный способ петли в схеме - это рекурсия хвоста. Мой код выглядит следующим образом:Эта функция схемы кажется хвостом рекурсивной, поэтому почему я получаю переполнение стека
(define (dbllink li)
(letrec ((step (lambda (lis prev head)
(if (null? lis)
head
(let ((cell (cons (car lis)
(cons prev '()))))
(if (null? prev)
(step (cdr lis);<--recursive call
cell
cell)
(begin (set-cdr! (cdr prev)
cell)
(step (cdr lis);<--recursive call
cell
head))))))))
(step li '() '())))
Я отметил, что я считаю только два рекурсивных вызова. Они оба кажутся мне в хвостовом контексте, согласно R6RS, но вызов функции вызывает переполнение стека. Любые идеи о том, почему?
Хм ... Это не должно быть круглым. То есть, следующий и предыдущий «поля» первого и последнего элементов соответственно должны быть пустыми. или вы просто подразумеваете, что маленькие круги формируются последовательными элементами, указывающими друг на друга назад и вперед? –
Вы правы. это то, что происходит. –