在我正在学习的计算机科学课程中,为了完成家庭作业,我们承担了几个与消息传递相关的不同问题。我已经能够解决除了一个之外的所有问题,其中包括以下内容:
编写一个不带参数的mailman对象工厂
(make-mailman)
返回一个消息传递对象,它响应以下消息:
'add-to-route
:返回一个接收任意数量的邮箱对象的过程 并将它们添加到mailman对象的“route”'collect-letters
:返回一个接受任意数量的字母对象的过程 收集它们以供将来分发'distribute
:将每个收集的信件添加到邮递员路线上的邮箱中 地址与字母的目的地匹配,并返回其目的地的任何字母的列表 与路线上的任何邮箱都不匹配(注意:每次通过后都没有'distribute
该 mailman对象应该没有收集的字母。)
为使代码更容易而给出的一些评论包括:
如果在一个分发回合中将多个字母分配到同一个邮箱,则为任何一个
它们可能是“最新”的字母,其消息是通过'get-latest-message
传递的
到邮箱。
没有两个邮箱具有相同的地址。
邮箱或信件不会多次传递给邮递员。
分发返回的不良信件不需要按特定顺序排列。
使用. args
语法接受任意数量的参数。
这是我能够为自己找到的:
(define (make-mailman)
(let ((T '()))
(define (route-adder . mobjects)
(assoc mobjects T))
(define (letter-collecter . lobjects)
(assoc lobjects T))
(define (add-to-route mobjects)
(begin (set! T (cons (route-adder . mobjects) T)) 'done))
(define (collect-letters lobjects)
(begin (set! T (cons (sort-strings (letter-collecter . lobjects)) T)) 'done))
(define (dispatch z)
(cond ((eq? z 'add-to-route) add-to-route)
((eq? z 'collect-letters) collect-letters)
((eq? z 'distribute) "unsure of what to do here")
(else "Invalid option")))
dispatch))
我可以在这里获得任何帮助,因为我已经尝试了一段时间来解决这个问题,并且无法从这里弄清楚该怎么做。
答案 0 :(得分:3)
您的代码有各种各样的混淆。 :)让我们一步一步地进行。
dispatch
位几乎没问题:
(define (make-mailman)
(let ...
...
(define (dispatch msg) ;; use short but suggestive var names
(cond
((eq? msg 'add-to-route) add-to-route)
((eq? msg 'collect-letters) collect-letters)
((eq? msg 'distribute)
;; "unsure of what to do here" <<-- Distribute the letters, what else?
distribute-the-letters)
(else "Invalid option")))
dispatch))
使用此类对象时,示例调用将为(define ob (make-mailman))
,然后为((ob 'add-to-route) box1 box2 ... boxn)
等。因此必须以这种方式定义add-to-route
过程:
(define (make-mailman)
(let ((self (list '(ROUTE) ; each mailman has a route, and a mailbag
'(MAILBAG)))) ; use suggestive name here (T, what T?)
...
(define (add-to-route . mailboxes)
(let ((route (assoc 'ROUTE self)))
(set-cdr! route
(append mailboxes ; there will be no duplicates
(cdr route)))
'DONE))
右?与字母相同:
(define (collect-letters . letters)
(let ((mailbag (assoc 'MAILBAG self)))
.....
'DONE))
现在我们可以处理缺失的部分distribute-the-letters
:
(define (distribute-the-letters)
;; for each letter in my mailbag
(let* ((mailbag (assoc 'MAILBAG self))
(mailboxes (cdr (assoc 'ROUTE self)))
(letters (cdr mailbag)))
(if (null? letters) ()
(let loop ((letter (car letters))
(letters (cdr letters))
(not-delivered ()))
;; access its address,
(let* ((address (letter 'get-address))
;; (we assume it supports this interface,
;; or maybe that's part of a previous assignment)
;; and find a mailbox on my route such that
(mbx (find-mailbox address mailboxes)))
;; its address matches the letter's
;; and if so,
(if .....
;; put that letter into this mailbox:
((mbx 'put-letter) letter)
;; (we assume it supports this interface,
;; or maybe that's part of a previous assignment)
;; but if not, add letter to the "not-delivered" list
..... )
(if (null? letters)
;; having emptied the mailbag, return the "not-delivered" list
(begin (set-cdr! mailbag nil) not-delivered)
(loop (car letters) (cdr letters) not-delivered)))))))
我们假设letter
和mailbox
个对象都支持消息类型'get-address
,它们都返回相同的address
类型的对象,{{1}对象支持mailbox
消息。
答案 1 :(得分:2)
除了消息功能的细节之外,看起来你已经钉了它。但是有一些错误:
此(route-adder . mobjects)
应为(router-adder objects)
,(letter-collector . lobjects)
也应如此。
不需要使用begin
。 (define (func . args) <body> ...)
的正文隐含在begin
中。
惯用法,您的代码可以写成:
(define (make-mailman)
(let ((T '()))
;; ...
(lambda (z)
(case z
((add-to-route) add-to-route)
((collect-letters) collect-letters)
((distribute) distribute)
(else (error "Invalid option"))))))
[但您可能还不知道case
还是lambda
还是......]
至于解决实际的消息传递功能。您将需要维护一组邮箱,其中每个邮箱将包含一组字母。一封信可能包含一个地址和一些内容(返回地址的额外信用)。分发行为将检查每个字母上的地址并将其存放在其邮箱中。邮递员需要持有信件(在他的路线上收集信件),直到指示分发。
为此,您可以从构建较低级别的功能开始,然后使用较低级别来构建实际的消息传递功能。从例如开始:
(define (make-letter addr content)
`(LETTER ,addr ,content))
(define letter-addr cadr)
;; ...
(define (make-mailbox addr)
'(MBOX ,addr))
(define mailbox-letters cddr)
(define (mailbox-letters-add mailbox letter)
(set-cdr! (cdr mailbox) (cons letter (mailbox-letters mailbox))))
;;...