最簡單的方法是簡單地使用庫函數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)
。我們有兩種選擇:我們可以在merge
正文中從combine
返回,或者我們可以反轉我們上面更改的行,使其成爲((list? lis) (combine (car lis) (combine (cdr lis) fine)))
。這意味着在添加當前元素之前,我們會將列表的其餘部分添加到fine
,這正是我們想要的。
另一個問題是我們需要將lis1
改爲lis2
,而不是相反。
最後一個問題是merge
正文中的cond
是不必要的 - 我們可以將其刪除。
作爲一個方面說明,通常認爲整齊的方法是不要給圓括號一個新的行,並將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) '()))