Как указывалось ранее, вам не нужно изменяемое состояние для выполнения вашей работы.Однако, если вы действительно хотите их использовать, вы можете легко изменить решение Keen, чтобы получить то, что вы хотите.Сначала вы должны перевести его код хвостовым рекурсивным способом.Вы можете начать с mkjump
(define (mkjump lst) (reverse (mkjump-tr lst '())))
(define (mkjump-tr lst sol)
(if (null? lst)
sol
(mkjump-tr (cdr lst)
(cons (cons (car lst) (wrapper (car lst) (cdr lst)))
sol)) ))
Затем вы можете изменить modmap
(define (modmap proc lst) (reverse (modmap-tr proc lst '())))
(define (modmap-tr proc lst sol)
(cond ((null? lst) sol)
((proc (car lst)) (modmap-tr proc
(cdr lst)
(cons (proc (car lst)) sol) ))
(else (modmap-tr proc (cdr lst) sol))))
Хвостовая рекурсия mkjump-tr
будет переведена в итеративный процесс.Это потому, что его можно рассматривать как цикл , а .Это позволит вам создать этот цикл со структурой do
.Таким образом, mkjump-tr
можно записать как
(define (mkjump-tr lst sol)
(do ((lst lst (cdr lst))
(sol sol (cons (cons (car lst) (wrapper (car lst) (cdr lst)))
sol)) )
((null? lst) sol)
))
, а modmap-tr
можно перевести как
(define (modmap-tr proc lst sol)
(do ((lst lst (cdr lst))
(sol sol (if (proc (car lst)) (cons (proc (car lst)) sol) sol)) )
((null? lst) sol)
))
Но поскольку у нас нет рекурсивной формы, мы можем записать их непосредственно do
в прежних функциях mkjump
и modmap
.Таким образом, мы получаем
(define (mkjump lst)
(do ((lst lst (cdr lst))
(sol '() (cons (cons (car lst) (wrapper (car lst) (cdr lst)))
sol)) )
((null? lst) (reverse sol))
))
(define (modmap proc lst)
(do ((lst lst (cdr lst))
(sol '() (if (proc (car lst)) (cons (proc (car lst)) sol) sol)) )
((null? lst) (reverse sol))
))
Вы можете увидеть некоторые небольшие изменения: reverse
добавляется перед sol
и sol
инициализируется пустым списком в обоих случаях.
Наконец, если вы действительно хотите где-то увидеть set!
, просто добавьте их, нарушив конструкцию do
-loop.Вот решение для mkjump
(define (mkjump lst)
(let ((elt 'undefined)
(lst lst)
(sol '()))
(do ()
((null? lst) (reverse sol))
(set! elt (car lst))
(set! lst (cdr lst))
(set! sol (cons (cons elt (wrapper elt lst)) sol))
)))
Я дам вам изменить modmap
.Эти две последние модификации запутывают идею алгоритма.Поэтому менять их таким способом - плохая идея, поскольку они ничего не улучшат.Однако первая модификация может быть хорошей идеей.Поэтому я предлагаю вам оставить первую модификацию.
Это то, что вы ожидали?