2015-05-31 35 views
2

由於標題暗示我試圖編寫一個方案函數來檢查列表中的所有元素是否都是唯一的。我已經寫了一些代碼,我認爲應該工作:試圖檢查一個列表中的所有元素是否都是唯一的

(define are-all-unique? 
     (lambda (v) 
     (if (member (car v) (cdr v)) 
      #f 
      (if (pair? v) 
       (are-all-unique? (cdr v)) 
       #t)))) 

,並在它是假的情況下工作正常,但如果我寫:

(are-all-unique? '(1 2 3)) 

返回:

Exception in car:() is not a pair 

有沒有人有關於如何解決這個問題的線索,以及我做錯了什麼? :)

回答

4

那麼,正如你的錯誤信息所述,你正試圖將空列表傳遞給car。至於爲什麼發生這種情況,讓我們來看看你的代碼。

正如我們所知,我們需要將cons單元格傳遞給carcdr以供他們使用。我們使用pair?來檢查這個屬性,你正在做什麼。問題是當你正在做

調試這種功能的最佳方式是跟蹤將錯誤輸入(在此例中爲'())傳遞給函數時發生的情況。首先要做的是在if聲明中運行測試:(member (car v) (cdr v))。現在,由於我們追蹤的輸入是空列表,所以每次都會失敗。你需要的是更多的東西是這樣的:

;; are-all-equal? is a poor choice of function name, by the way, since that's 
;; not really what this function checks 
(define are-all-unique? 
    (lambda (v) 
    (if (pair? v) 
     ; The only way that this branch will ever execute is 
     ; if (pair? v) is true, so we know that (car v) and (cdr v) 
     ; will never raise any exceptions 
     (and (not (member (car v) (cdr v))) 
      (are-all-unique? (cdr v))) 
     #t))) 

這裏要注意的一點是這個版本的功能的控制流結構:一個適當的列表可爲cons細胞或空列表,所以我們有我們的功能中有兩種情況(每種情況都有一種情況)。在編寫處理列表的函數時,應該(大多數情況下)決定在非空和空的情況下要做什麼,並將函數內部的第一件事情發送給適當的情況。這種方法在進行結構遞歸時是適當的(即用我的一名新生教授的話來說,「數據結構通知你的代碼結構」)。

相關問題