Общий рецепт "итеративной процедуры":
- Напишите вспомогательную функцию, которая принимает параметр аккумулятора.
Создайте каждый промежуточный результат в аккумуляторе.
- Когда вы закончите рекурсию, верните аккумулятор.
- Передайте ему подходящий начальный аккумулятор.
Обычно при преобразовании списков накапливается результат в обратном порядке, а затем, когда вы закончите, результат инвертируется.
Тривиальный пример, увеличивающий каждый элемент списка на единицу:
(define (add-1 ls)
(if (null? ls)
'()
(cons (+ 1 (car ls)) (add-1 (cdr ls)))))
Чтобы сделать его итеративным, создайте вспомогательную функцию, в которой вы cons
собираете аккумулятор вместо рекурсивного результата:
(define (add-one ls acc)
(if (null? ls)
(reverse acc)
(add-one (cdr ls) (cons (+ 1 (car ls)) acc))))
(Обратите внимание, что за исключением введения acc
, рекурсия содержит те же части, что и раньше, но в другом порядке.)
Затем вы запускаете его с пустым аккумулятором:
(define (add-1 ls)
(add-one ls '()))
В вашем случае несколько больше базовых случаев, так как вам нужно разместить входы разной длины.
Завершение его осталось как упражнение.
(Другое упражнение: выясните, почему ваше первое условие, (and (null? l1) (null? l2))
, не нужно.)