Самый простой способ это просто использовать библиотечную функцию flatten
.
(define (merge lis1 lis2)
(flatten (cons lis1 lis2)))
flatten
принимает список, который может содержать списки (которые в свою очередь могут содержать больше списков, ...) и сглаживает результат в список лиц, не являющихся списками, что и ваша скомбинировать функция, кажется, пытается делать.
(flatten '(1 2 (3 (4 5) 6)))
возвращает '(1 2 3 4 5 6)
Если эта функция библиотеки соваться, ваш код на самом деле очень близко к правильному.
Первый выпуск находится на линии ((list? lis) (combine (car lis) fine) (combine (cdr lis) fine) )
. fine
никогда не изменяется, поэтому код оценивает (combine (car lis) fine)
и затем возвращает (combine (cdr lis) fine)
, где fine
во втором выражении является исходным значением fine
. Эта строка - это то же самое, что и ((list? lis) (combine (cdr lis) fine) )
, что явно не то, что мы хотим. Вместо этого мы должны использовать первое выражение во втором выражении ((list? lis) (combine (cdr lis) (combine (car lis) fine)))
.
Вторая проблема заключается в том, что в комбайне, когда lis
является нулевым, нам необходимо вернуть fine
, а не lis
.
Следующая проблема заключается в том, что этот код проходит через список, принимает первый элемент lis
и помещает его в начало fine
, а затем передает вновь созданный список и использует его для следующей итерации функции, где он принимает второе значение в lis
и прикрепляет его к передней части нового fine
, перед первым значением lis
. Результаты в порядке возврата возвращаемого значения fine
- (merge '(1 2 (3)) '(4 (5 6)))
вернутся (6 5 4 3 2 1)
. У нас есть два варианта: мы можем называть обратное по возврату от combine
в теле merge
, или мы можем инвертировать линию, которую мы изменили выше, делая ее ((list? lis) (combine (car lis) (combine (cdr lis) fine)))
. Это означает, что мы добавим остальную часть списка в fine
перед добавлением текущего элемента, который мы хотим.
Другая проблема заключается в том, что нам нужны минусы lis1
до lis2
, а не наоборот.
Последний выпуск: cond
в корпусе merge
не нужно - мы можем его удалить.
В качестве примечания стороны, как правило, считается более аккуратным, чтобы не давать близких круглых скобок новую строку и отступать от тела define
или cond
всего двумя пробелами.
С учетом всех этих изменений, окончательный код:
(define (merge lis1 lis2)
(define (combine lis fine)
(cond
((null? lis) fine)
((list? lis) (combine (car lis)
(combine (cdr lis) fine)))
(else (cons lis fine))))
(combine (cons lis1 lis2) '()))