正如錯誤信息所解釋的那樣,您的問題在於您正在嘗試顛倒數字。首先,讓我們刪除一些不必要的條件並調試程序中的東西,以達到這個更簡單的程序。讓我們一步步通過這個程序,看看發生了什麼事情:
(define (deep-reverse lst)
(if (null? lst)
'()
(append (deep-reverse (cdr lst)) (list (reverse (car lst))))))
我們先從
(deep-reverse '(1 (b c) (a b)))
代的說法,我們得到
(if (null? '(1 (b c) (a b)))
'()
(append (deep-reverse (cdr '(1 (b c) (a b))))
(list (reverse (car '(1 (b c) (a b)))))))
由於病情#f
,簡化爲
(append (deep-reverse (cdr '(1 (b c) (a b))))
(list (reverse (car '(1 (b c) (a b))))))
要評估第一個參數,請首先找到cdr
,然後在其上調用deep-reverse
。我將跳過這裏的步驟,但您應該能夠輕鬆地測試它是否正常工作。
(append '((b a) (c b)) (list (reverse (car '(1 (b c) (a b))))))
下一步,我們評估car
:
(append '((b a) (c b)) (list (reverse 1)))
在這裏,我們看到的是什麼問題,我們不能扭轉單號!
的問題是,你的deep-reverse
應該有遞歸兩種截然不同的行爲:
- 一個數字或符號,或其他非列表實體,沒有做任何事情,因爲它沒有任何意義反向名單上的一個號碼
- ,深扭轉它
有兩個原因,當前的程序並沒有這樣做正確:
- 它只對列表元素進行淺反轉;也就是說,它不會深扭轉
'(((a b) (c d)) ((e f) (g h)))
正確
- ,如果它曾經遇到一些或其他非列表,像一個符號
最簡單的解決方法是添加一個條件,以檢查它是否是一個失敗先試圖扭轉它,然後再試一下pair?
。如果不是pair?
,然後lst
必須是nil
(我們可能留下不變化)或一個非列表對象(我們也可以離開原樣)
(define (deep-reverse lst)
(if (pair? lst)
(append (deep-reverse (cdr lst)) (list (deep-reverse (car lst))))
lst))
最後,我要指出的是,我們在這裏使用的模式實際上是一個foldr
模式。我們可以抽象掉這種模式與foldr
:
(define (deep-reverse xs)
(cond ((pair? xs)
(foldr (lambda (x y) (append y (list (deep-reverse x)))) '() xs))
(else xs)))
但是我們也注意到,這是低效的,因爲append
是昂貴的操作。修改算法尾遞歸一個清楚地表明,這其實是一個foldl
:
(define (deep-reverse xs)
(cond ((pair? xs)
(foldl (lambda (x y) (cons (deep-reverse x) y)) '() xs))
(else xs)))
它是如何這樣的功能可能會被寫在典型的慣用方案,或由威爾·內斯指出,
(define (deep-reverse xs)
(cond ((pair? xs) (reverse (map deep-reverse xs)))
(else xs)))
在紙上做了什麼,解決問題的方法(所有這些方法)。謝謝!如果我可能會問,究竟是什麼(if(null?list))是什麼意思?列表來自哪裏,還是隻有一個? – AlwaysLearning
@AlwaysLearning對不起,我的意思是'lst'。我已更正它,謝謝指出錯誤! –
如果'lst'是'pair?'是從不'null?' – Sylwester