I need some advice on abstracting the find
and check-callback
functions. The code works fine, but it seems that there is a lot of unnecessary repetition. Is there a more elegant way to re-write them?
;; Model
(define-struct contact (name phone))
(define phonebook (list (make-contact 'adam 5551212)
(make-contact 'brian 5552323)
(make-contact 'chris 5558888)))
;; find: (string->symbol, string->number) item (listof items) -> symbol/number/false
(define (find type item pb)
(cond
[(empty? pb) false]
[(equal? (string->symbol item) (contact-name (first pb))) (contact-phone (first pb))]
[(equal? (string->number item) (contact-phone (first pb))) (contact-name (first pb))]
[else (find type item (rest pb))]))
;; Controller
(define (check-callback b)
(cond
[(number? (find str开发者_如何学Cing->symbol (text-contents a-text-field) phonebook))
(draw-message a-msg (number->string (find string->symbol (text-contents a-text-field) phonebook)))]
[(symbol? (find string->number (text-contents a-text-field) phonebook))
(draw-message a-msg (symbol->string (find string->number (text-contents a-text-field) phonebook)))]
[else (draw-message a-msg "Not found")]))
;; View
(define a-text-field
(make-text "Enter a name or phone number"))
(define a-msg
(make-message ""))
(define a-button
(make-button "Search" check-callback))
(create-window
(list (list a-text-field)
(list a-button)
(list a-msg)))
Since the type
variable is not used, I omitted it from the code and made some refactoring:
;; find
(define (find item pb)
(let* ((first-pb (first pb))
(name (contact-name first-pb))
(phone (contact-phone first-pb)))
(cond
[(empty? pb) #f]
[(equal? (string->symbol item) name) phone]
[(equal? (string->number item) phone) name]
[else (find item (rest pb))])))
;; Controller
(define (check-callback pb)
(let ((res (find (text-contents a-text-field) pb)))
(draw-message a-msg
(cond
[(number? res) (number->string res)]
[(symbol? res) (symbol->string res)]
[else "Not found"]))))
Or you could just convert your name and phone to string at once:
;; find
(define (find item pb)
(let* ((first-pb (first pb))
(name (contact-name first-pb))
(phone (contact-phone first-pb)))
(cond
[(empty? pb) #f]
[(equal? (string->symbol item) name) (number->string phone)]
[(equal? (string->number item) phone) (symbol->string name)]
[else (find item (rest pb))])))
;; Controller
(define (check-callback pb)
(let ((res (find (text-contents a-text-field) pb)))
(draw-message a-msg
(if (res)
res
"Not found"))))
精彩评论