瞭解這個問題的第一步是明確說明我們正在處理的數據由什麼組成。讓我們寫下了一系列的數據定義的:
;; A ZIP is a number
;; A CITY is a symbol
;; A STATE is a symbol
的ENTRY
是ZIP
,一個CITY
和STATE
的列表。回想一下,列表是一系列以null結尾的cons單元。讓我們使用明確的呼籲ENTRY
我們的數據定義寫入cons
:
;; An ENTRY is of the form (cons ZIP (cons CITY (cons STATE null)))
;; A [listof ENTRY] is either:
;;
;; 1. The empty list, null, or
;; 2. (cons ENTRY [listof ENTRY])
有了這些數據定義在手更容易得到準確的是我們希望我們的函數來完成。我們將爲我們的函數寫下一個契約,它由兩部分組成:函數名稱和函數消耗的數據類型以及函數產生的數據類型。例如:
;; <FUNCTION NAME> : <WHAT OUR FUNCTION CONSUMES> -> <WHAT OUR FUNCTION PRODUCES>
現在我們可以寫我們要寫的功能合同:
;; find : STATE [listof ENTRY] -> [listof ZIP]
;; Produces the ZIPs in [listof ENTRY] that match the given STATE.
(define (find state entries)
...)
;; findzips : STATE -> [listof ZIP]
;; Produces the ZIPs in 'zipcodes' that match the given STATE.
(define (findzips state)
...)
讓我們開始定義爲填充find
。根據我們的合同,我們知道'find'有兩個參數,一個是STATE
和一個[listof ENTRY]
。我們從[listof ENTRY]
的數據定義知道它可以是以下兩件事之一:(cons ENTRY [listof ENTRY])
或null
。任何時候,我們不得不處理一個以上的情況下,我們可以使用cond
我們想要在各種情況下的行爲:
;; find : STATE [listof ENTRY] -> [listof ZIP]
;; Produces the ZIPs for which there is an ENTRY in the [listof ENTRY]
;; with a STATE that matches the one given.
(define (find state entries)
(cond ((null? entries) ...)
(else ...)))
參考教科書或問你的教練,如果cond
是不熟悉的。
到目前爲止這麼好。那麼如果我們的函數被稱爲null(根據我們的合同,是一個有效的輸入),我們該如何返回?我們的合同建議我們應該返回一個空白列表作爲回報。
;; find : STATE [listof ENTRY] -> [listof ZIP]
(define (find state entries)
(cond ((null? entries) null)
(else ...)))
到目前爲止好。現在是困難的部分。如果輸入列表不是空的,那麼它必須包含至少一個ENTRY
。對於任何給定的ENTRY
,我們必須處理兩種情況:條目中的狀態與我們正在查找的STATE
相匹配,或者不匹配。假設我們有一個函數get-state
,給定一個ENTRY
,它給我們它的STATE
。
;; find : STATE [listof ENTRY] -> [listof ZIP]
(define (find state entries)
(cond ((null? entries) null)
(else (if (equal? state
(get-state (car entries)))
... ;; matches
...)))) ;; doesn't match
讓我們先處理第二種情況。在情況下,我們要搜索中的條目不匹配,在未來ENTRY
的STATE
的STATE
我們只是想匹配列表中的其他任何ZIP
秒。看看'找到'的合同,我們可以看到,在列表的其餘部分找到正確的東西將會給我們我們想要的東西!灌裝,在我們有:
;; find : STATE [listof ENTRY] -> [listof ZIP]
(define (find state entries)
(cond ((null? entries) null)
(else (if (equal? state
(get-state (car entries)))
... ;; matches
...)))) ;; doesn't match
在第一種情況下,我們知道,在「entires」第一ENTRY
具有我們正在尋找的STATE
相匹配的狀態。考慮一下,我們希望爲我們的最終結果在這種情況下:我們希望能有名單與我們已經知道了ZIP
開始匹配我們正在尋找跟任何其他ZIP
s的狀態也匹配的entries
其餘STATE
。我們可以使用cons
來構建一個新的列表。 cons
有如下合同:
;; cons : any [listof any] -> [listof any]
的第一個參數cons
很簡單。我們再假設我們有一個函數'get-zip',該函數給出了給定ENTRY
的ZIP
。然後,我們可以簡單地提取從ENTRY
的ZIP
:
;; find : STATE [listof ENTRY] -> [listof ZIP]
(define (find state entries)
(cond ((null? entries) null)
(else (if (equal? state
(get-state (car entries)))
(cons (get-zip (car entries))
...)
(find state (cdr entries))))))
的第二個參數cons
我會留下作爲一個練習給你。我們差不多完成了!現在我們有find
寫作findzips
是微不足道的。我們只需將find
與給定的STATE
和zipcodes
作爲參數。填寫剩餘的省略號,你會完成:
;; get-zip : ENTRY -> ZIP
;; Produces the ZIP for a given ENTRY.
(define (get-zip entry)
...)
;; get-state : ENTRY -> STATE
;; Produces the STATE for a given ENTRY.
(define (get-state entry)
...)
;; find : STATE [listof ENTRY] -> [listof ZIP]
;; Produces the ZIPs in [listof ENTRY] that match the given STATE.
(define (find state entries)
(cond ((null? entries) null)
(else (if (equal? state
(get-state (car entries)))
(cons (get-zip (car entries))
...)
(find state (cdr entries))))))
;; findzips : STATE -> [listof ZIP]
;; Produces the ZIPs in 'zipcodes' that match the given STATE.
(define (findzips state)
(find state zipcodes))
在解決這個問題,我們利用「設計方」,一步一步的指導,以設計方案的元素。 Felleisen,Findler,Flatt和Krishnamurthi在「如何設計程序」中全面概述了「設計食譜」。全文可在線獲取:www.htdp.org。
祝你好運!
「*我不允許*」 - >作業?哦,請縮進你的代碼。 – 2011-05-24 21:52:48
我不明白?它不是一個完整的家庭作業只是一個部分,我麻煩它..我試圖弄清楚它..也我嘗試編寫代碼與「(定義(findzips x) (找到x zipcodes)) (定義find (lambda(x zipcodes) (if(EQ?x(caddr(car zipcodes)))(list(car(car zipcodes)))(find3 x(cdr zipcodes)))))「但是我不行,我正在尋求幫助創建列表.. – Palindrom 2011-05-24 21:58:37